summaryrefslogtreecommitdiff
path: root/bsps/arm/stm32h7/hal
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2020-03-04 12:33:17 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2020-10-20 17:57:54 +0200
commit44c8a1777f4a3bd619676c16852cb8764369a8ec (patch)
treed85e571c49271310bc58c7d10d28c4af45ae0cf6 /bsps/arm/stm32h7/hal
parente39da486b8b8b783ffd9a2159164f047bbeed561 (diff)
bsp/stm32h7: Import from STM32CubeMX-5.6.0
Update #3910.
Diffstat (limited to 'bsps/arm/stm32h7/hal')
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal.c1276
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_adc.c3713
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_adc_ex.c2492
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_cec.c1001
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_comp.c1250
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_cortex.c533
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_crc.c518
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_crc_ex.c225
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_cryp.c5145
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_cryp_ex.c446
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dac.c1534
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dac_ex.c869
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dcmi.c1227
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dfsdm.c3798
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dfsdm_ex.c135
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dma.c2055
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dma2d.c2167
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dma_ex.c714
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c2705
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_dts.c823
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_eth.c2998
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_eth_ex.c559
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_exti.c877
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_fdcan.c6169
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_flash.c1099
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_flash_ex.c1709
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_gfxmmu.c893
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_gpio.c560
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_hash.c3445
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_hash_ex.c1030
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_hcd.c1648
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_hrtim.c9277
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_hsem.c441
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_i2c.c6635
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_i2c_ex.c339
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_i2s.c1946
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_i2s_ex.c28
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_irda.c2898
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_iwdg.c265
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_jpeg.c4199
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_lptim.c2540
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_ltdc.c2163
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_ltdc_ex.c149
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_mdios.c957
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c1901
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_mmc.c3054
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_mmc_ex.c304
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_nand.c2183
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_nor.c1285
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_opamp.c1163
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_opamp_ex.c435
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_ospi.c3068
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_otfdec.c998
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_pcd.c2201
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_pcd_ex.c348
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_pssi.c1798
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_pwr.c868
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_pwr_ex.c2100
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_qspi.c2645
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_ramecc.c692
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_rcc.c1775
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_rcc_ex.c3437
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_rng.c927
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_rng_ex.c299
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_rtc.c2144
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_rtc_ex.c3017
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_sai.c2920
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_sai_ex.c135
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_sd.c3942
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_sd_ex.c305
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_sdram.c1312
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_smartcard.c3136
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_smartcard_ex.c494
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_smbus.c2673
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_spdifrx.c1635
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_spi.c3836
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_spi_ex.c229
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_sram.c1113
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_swpmi.c1949
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_tim.c7047
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_tim_ex.c2324
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_uart.c4115
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c729
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_usart.c3684
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_usart_ex.c538
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_wwdg.c414
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_adc.c1080
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_bdma.c346
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_comp.c296
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_crc.c115
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_crs.c86
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_dac.c349
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_delayblock.c210
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_dma.c423
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_dma2d.c635
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_exti.c458
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_fmc.c1090
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_gpio.c307
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_hrtim.c83
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_i2c.c243
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_lptim.c355
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_lpuart.c283
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_mdma.c782
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_opamp.c230
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_pwr.c82
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_rcc.c1770
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_rng.c158
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_rtc.c894
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_sdmmc.c1582
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_spi.c738
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_swpmi.c179
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_tim.c1380
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_usart.c496
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_usb.c1989
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_ll_utils.c975
115 files changed, 182236 insertions, 0 deletions
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal.c
new file mode 100644
index 0000000000..3e92312e99
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal.c
@@ -0,0 +1,1276 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal.c
+ * @author MCD Application Team
+ * @brief HAL module driver.
+ * This is the common part of the HAL initialization
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The common HAL driver contains a set of generic and common APIs that can be
+ used by the PPP peripheral drivers and the user to start using the HAL.
+ [..]
+ The HAL contains two APIs' categories:
+ (+) Common HAL APIs
+ (+) Services HAL APIs
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 V1.8.0
+ */
+#define __STM32H7xx_HAL_VERSION_MAIN (0x01UL) /*!< [31:24] main version */
+#define __STM32H7xx_HAL_VERSION_SUB1 (0x08UL) /*!< [23:16] sub1 version */
+#define __STM32H7xx_HAL_VERSION_SUB2 (0x00UL) /*!< [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 ---------------------------------------------------------*/
+
+/** @defgroup HAL_Private_Functions HAL Private Functions
+ * @{
+ */
+
+/** @defgroup HAL_Group1 Initialization and de-initialization Functions
+ * @brief Initialization and de-initialization functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initializes the Flash interface the NVIC allocation and initial clock
+ configuration. It initializes the systick also when timeout is needed
+ and the backup domain when enabled.
+ (+) De-Initializes common part of the HAL.
+ (+) Configure The time base source to have 1ms time base with a dedicated
+ Tick interrupt priority.
+ (++) SysTick timer is used by default as source of time base, but user
+ can eventually implement his proper time base source (a general purpose
+ timer for example or other time source), keeping in mind that Time base
+ duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
+ handled in milliseconds basis.
+ (++) Time base configuration function (HAL_InitTick ()) is called automatically
+ at the beginning of the program after reset by HAL_Init() or at any time
+ when clock is configured, by HAL_RCC_ClockConfig().
+ (++) Source of time base is configured to generate interrupts at regular
+ time intervals. Care must be taken if HAL_Delay() is called from a
+ peripheral ISR process, the Tick interrupt line must have higher priority
+ (numerically lower) than the peripheral interrupt. Otherwise the caller
+ ISR process will be blocked.
+ (++) functions affecting time base configurations are declared as __weak
+ to make override possible in case of other implementations in user file.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function is used to initialize the HAL Library; it must be the first
+ * instruction to be executed in the main program (before to call any other
+ * HAL function), it performs the following:
+ * 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 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;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_Group2 HAL Control functions
+ * @brief HAL Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### HAL Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Provide a tick value in millisecond
+ (+) Provide a blocking delay in millisecond
+ (+) Suspend the time base source interrupt
+ (+) Resume the time base source interrupt
+ (+) Get the HAL API driver version
+ (+) Get the device identifier
+ (+) Get the device revision identifier
+ (+) Enable/Disable Debug module during SLEEP mode
+ (+) Enable/Disable Debug module during STOP mode
+ (+) Enable/Disable Debug module during STANDBY mode
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function is called to increment a global variable "uwTick"
+ * used as application time base.
+ * @note In the default implementation, this variable is incremented each 1ms
+ * in Systick ISR.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval None
+ */
+__weak void HAL_IncTick(void)
+{
+ uwTick += (uint32_t)uwTickFreq;
+}
+
+/**
+ * @brief Provides a tick value in millisecond.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval tick value
+ */
+__weak uint32_t HAL_GetTick(void)
+{
+ return uwTick;
+}
+
+/**
+ * @brief This function returns a tick priority.
+ * @retval tick priority
+ */
+uint32_t HAL_GetTickPrio(void)
+{
+ return uwTickPrio;
+}
+
+/**
+ * @brief Set new tick Freq.
+ * @retval Status
+ */
+HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_TickFreqTypeDef prevTickFreq;
+
+ assert_param(IS_TICKFREQ(Freq));
+
+ if (uwTickFreq != Freq)
+ {
+
+ /* Back up uwTickFreq frequency */
+ prevTickFreq = uwTickFreq;
+
+ /* Update uwTickFreq global variable used by HAL_InitTick() */
+ uwTickFreq = Freq;
+
+ /* Apply the new tick Freq */
+ status = HAL_InitTick(uwTickPrio);
+ if (status != HAL_OK)
+ {
+ /* Restore previous tick frequency */
+ uwTickFreq = prevTickFreq;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Return tick frequency.
+ * @retval tick period in Hz
+ */
+HAL_TickFreqTypeDef HAL_GetTickFreq(void)
+{
+ return uwTickFreq;
+}
+
+/**
+ * @brief This function provides minimum delay (in milliseconds) based
+ * on variable incremented.
+ * @note In the default implementation , SysTick timer is the source of time base.
+ * It is used to generate interrupts at regular time intervals where uwTick
+ * is incremented.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @param Delay specifies the delay time length, in milliseconds.
+ * @retval None
+ */
+__weak void HAL_Delay(uint32_t Delay)
+{
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t wait = Delay;
+
+ /* Add a freq to guarantee minimum wait */
+ if (wait < HAL_MAX_DELAY)
+ {
+ wait += (uint32_t)(uwTickFreq);
+ }
+
+ while ((HAL_GetTick() - tickstart) < wait)
+ {
+ }
+}
+
+/**
+ * @brief Suspend Tick increment.
+ * @note In the default implementation , SysTick timer is the source of time base. It is
+ * used to generate interrupts at regular time intervals. Once HAL_SuspendTick()
+ * is called, the the SysTick interrupt will be disabled and so Tick increment
+ * is suspended.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval None
+ */
+__weak void HAL_SuspendTick(void)
+{
+ /* Disable SysTick Interrupt */
+ SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
+}
+
+/**
+ * @brief Resume Tick increment.
+ * @note In the default implementation , SysTick timer is the source of time base. It is
+ * used to generate interrupts at regular time intervals. Once HAL_ResumeTick()
+ * is called, the the SysTick interrupt will be enabled and so Tick increment
+ * is resumed.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval None
+ */
+__weak void HAL_ResumeTick(void)
+{
+ /* Enable SysTick Interrupt */
+ SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
+}
+
+/**
+ * @brief Returns the HAL revision
+ * @retval version : 0xXYZR (8bits for each decimal, R for RC)
+ */
+uint32_t HAL_GetHalVersion(void)
+{
+ return __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.048 V.
+ * This requires VDDA equal to or higher than 2.4 V.
+ * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE1: VREF_OUT2 around 2.5 V.
+ * This requires VDDA equal to or higher than 2.8 V.
+ * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE2: VREF_OUT3 around 1.5 V.
+ * This requires VDDA equal to or higher than 1.8 V.
+ * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE3: VREF_OUT4 around 1.8 V.
+ * This requires VDDA equal to or higher than 2.1 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 2.4 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 2.4 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 */
+
+/**
+ * @brief Enable the Debug Module during Domain1/CDomain SLEEP mode
+ * @retval None
+ */
+void HAL_EnableDBGSleepMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEPD1);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain1/CDomain SLEEP mode
+ * @retval None
+ */
+void HAL_DisableDBGSleepMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEPD1);
+}
+
+
+/**
+ * @brief Enable the Debug Module during Domain1/CDomain STOP mode
+ * @retval None
+ */
+void HAL_EnableDBGStopMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOPD1);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain1/CDomain STOP mode
+ * @retval None
+ */
+void HAL_DisableDBGStopMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOPD1);
+}
+
+/**
+ * @brief Enable the Debug Module during Domain1/CDomain STANDBY mode
+ * @retval None
+ */
+void HAL_EnableDBGStandbyMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBYD1);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain1/CDomain STANDBY mode
+ * @retval None
+ */
+void HAL_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*/
+
+/**
+ * @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);
+}
+
+/**
+ * @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);
+}
+
+/**
+ * @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)));
+
+}
+
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_adc.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_adc.c
new file mode 100644
index 0000000000..cce8bf9baa
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_adc.c
@@ -0,0 +1,3713 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_adc.c
+ * @author MCD Application Team
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Analog to Digital Convertor (ADC)
+ * peripheral:
+ * + Initialization and de-initialization functions
+ * ++ Initialization and Configuration of ADC
+ * + Operation functions
+ * ++ Start, stop, get result of conversions of regular
+ * group, using 3 possible modes: polling, interruption or DMA.
+ * + Control functions
+ * ++ Channels configuration on regular group
+ * ++ Analog Watchdog configuration
+ * + State functions
+ * ++ ADC state machine management
+ * ++ Interrupts and flags management
+ * Other functions (extended functions) are available in file
+ * "stm32h7xx_hal_adc_ex.c".
+ *
+ @verbatim
+ ==============================================================================
+ ##### ADC peripheral features #####
+ ==============================================================================
+ [..]
+ (+) 16-bit, 14-bit, 12-bit, 10-bit or 8-bit configurable resolution.
+
+ (+) Interrupt generation at the end of regular conversion and in case of
+ analog watchdog or overrun events.
+
+ (+) Single and continuous conversion modes.
+
+ (+) Scan mode for conversion of several channels sequentially.
+
+ (+) Data alignment with in-built data coherency.
+
+ (+) Programmable sampling time (channel wise)
+
+ (+) External trigger (timer or EXTI) with configurable polarity
+
+ (+) DMA request generation for transfer of conversions data of regular group.
+
+ (+) Configurable delay between conversions in Dual interleaved mode.
+
+ (+) ADC channels selectable single/differential input.
+
+ (+) ADC offset shared on 4 offset instances.
+ (+) ADC calibration
+
+ (+) ADC conversion of regular group.
+
+ (+) ADC supply requirements: 1.62 V to 3.6 V.
+
+ (+) ADC input range: from Vref- (connected to Vssa) to Vref+ (connected to
+ Vdda or to an external voltage reference).
+
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+
+ *** Configuration of top level parameters related to ADC ***
+ ============================================================
+ [..]
+
+ (#) Enable the ADC interface
+ (++) As prerequisite, ADC clock must be configured at RCC top level.
+
+ (++) Two clock settings are mandatory:
+ (+++) ADC clock (core clock, also possibly conversion clock).
+
+ (+++) ADC clock (conversions clock).
+ Two possible clock sources: synchronous clock derived from AHB clock
+ or asynchronous clock derived from system clock, the PLL2 or the PLL3 running up to 400MHz.
+
+ (+++) Example:
+ Into HAL_ADC_MspInit() (recommended code location) or with
+ other device clock parameters configuration:
+ (+++) __HAL_RCC_ADC_CLK_ENABLE(); (mandatory)
+
+ RCC_ADCCLKSOURCE_PLL2 enable: (optional: if asynchronous clock selected)
+ (+++) RCC_PeriphClkInitTypeDef RCC_PeriphClkInit;
+ (+++) PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
+ (+++) PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
+ (+++) HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
+
+ (++) ADC clock source and clock prescaler are configured at ADC level with
+ parameter "ClockPrescaler" using function HAL_ADC_Init().
+
+ (#) ADC pins configuration
+ (++) Enable the clock for the ADC GPIOs
+ using macro __HAL_RCC_GPIOx_CLK_ENABLE()
+ (++) Configure these ADC pins in analog mode
+ using function HAL_GPIO_Init()
+
+ (#) Optionally, in case of usage of ADC with interruptions:
+ (++) Configure the NVIC for ADC
+ using function HAL_NVIC_EnableIRQ(ADCx_IRQn)
+ (++) Insert the ADC interruption handler function HAL_ADC_IRQHandler()
+ into the function of corresponding ADC interruption vector
+ ADCx_IRQHandler().
+
+ (#) Optionally, in case of usage of DMA:
+ (++) Configure the DMA (DMA channel, mode normal or circular, ...)
+ using function HAL_DMA_Init().
+ (++) Configure the NVIC for DMA
+ using function HAL_NVIC_EnableIRQ(DMAx_Channelx_IRQn)
+ (++) Insert the ADC interruption handler function HAL_ADC_IRQHandler()
+ into the function of corresponding DMA interruption vector
+ DMAx_Channelx_IRQHandler().
+
+ *** Configuration of ADC, group regular, channels parameters ***
+ ================================================================
+ [..]
+
+ (#) Configure the ADC parameters (resolution, data alignment, ...)
+ and regular group parameters (conversion trigger, sequencer, ...)
+ using function HAL_ADC_Init().
+
+ (#) Configure the channels for regular group parameters (channel number,
+ channel rank into sequencer, ..., into regular group)
+ using function HAL_ADC_ConfigChannel().
+
+ (#) Optionally, configure the analog watchdog parameters (channels
+ monitored, thresholds, ...)
+ using function HAL_ADC_AnalogWDGConfig().
+
+ *** Execution of ADC conversions ***
+ ====================================
+ [..]
+
+ (#) Optionally, perform an automatic ADC calibration to improve the
+ conversion accuracy
+ using function HAL_ADCEx_Calibration_Start().
+
+ (#) ADC driver can be used among three modes: polling, interruption,
+ transfer by DMA.
+
+ (++) ADC conversion by polling:
+ (+++) Activate the ADC peripheral and start conversions
+ using function HAL_ADC_Start()
+ (+++) Wait for ADC conversion completion
+ using function HAL_ADC_PollForConversion()
+ (+++) Retrieve conversion results
+ using function HAL_ADC_GetValue()
+ (+++) Stop conversion and disable the ADC peripheral
+ using function HAL_ADC_Stop()
+
+ (++) ADC conversion by interruption:
+ (+++) Activate the ADC peripheral and start conversions
+ using function HAL_ADC_Start_IT()
+ (+++) Wait for ADC conversion completion by call of function
+ HAL_ADC_ConvCpltCallback()
+ (this function must be implemented in user program)
+ (+++) Retrieve conversion results
+ using function HAL_ADC_GetValue()
+ (+++) Stop conversion and disable the ADC peripheral
+ using function HAL_ADC_Stop_IT()
+
+ (++) ADC conversion with transfer by DMA:
+ (+++) Activate the ADC peripheral and start conversions
+ using function HAL_ADC_Start_DMA()
+ (+++) Wait for ADC conversion completion by call of function
+ HAL_ADC_ConvCpltCallback() or HAL_ADC_ConvHalfCpltCallback()
+ (these functions must be implemented in user program)
+ (+++) Conversion results are automatically transferred by DMA into
+ destination variable address.
+ (+++) Stop conversion and disable the ADC peripheral
+ using function HAL_ADC_Stop_DMA()
+
+ [..]
+
+ (@) Callback functions must be implemented in user program:
+ (+@) HAL_ADC_ErrorCallback()
+ (+@) HAL_ADC_LevelOutOfWindowCallback() (callback of analog watchdog)
+ (+@) HAL_ADC_ConvCpltCallback()
+ (+@) HAL_ADC_ConvHalfCpltCallback
+
+ *** Deinitialization of ADC ***
+ ============================================================
+ [..]
+
+ (#) Disable the ADC interface
+ (++) ADC clock can be hard reset and disabled at RCC top level.
+ (++) Hard reset of ADC peripherals
+ using macro __HAL_RCC_ADCx_FORCE_RESET(), __HAL_RCC_ADCx_RELEASE_RESET().
+ (++) ADC clock disable
+ using the equivalent macro/functions as configuration step.
+ (+++) Example:
+ Into HAL_ADC_MspDeInit() (recommended code location) or with
+ other device clock parameters configuration:
+ (+++) __HAL_RCC_ADC_CLK_DISABLE(); (if not used anymore)
+ RCC_ADCCLKSOURCE_CLKP restore: (optional)
+ (+++) RCC_PeriphClkInitTypeDef RCC_PeriphClkInit;
+ (+++) PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
+ (+++) PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_CLKP;
+ (+++) HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
+
+ (#) ADC pins configuration
+ (++) Disable the clock for the ADC GPIOs
+ using macro __HAL_RCC_GPIOx_CLK_DISABLE()
+
+ (#) Optionally, in case of usage of ADC with interruptions:
+ (++) Disable the NVIC for ADC
+ using function HAL_NVIC_EnableIRQ(ADCx_IRQn)
+
+ (#) Optionally, in case of usage of DMA:
+ (++) Deinitialize the DMA
+ using function HAL_DMA_Init().
+ (++) Disable the NVIC for DMA
+ using function HAL_NVIC_EnableIRQ(DMAx_Channelx_IRQn)
+
+ [..]
+
+ *** Callback registration ***
+ =============================================
+ [..]
+
+ The compilation flag USE_HAL_ADC_REGISTER_CALLBACKS, when set to 1,
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions @ref HAL_ADC_RegisterCallback()
+ to register an interrupt callback.
+ [..]
+
+ Function @ref HAL_ADC_RegisterCallback() allows to register following callbacks:
+ (+) ConvCpltCallback : ADC conversion complete callback
+ (+) ConvHalfCpltCallback : ADC conversion DMA half-transfer callback
+ (+) LevelOutOfWindowCallback : ADC analog watchdog 1 callback
+ (+) ErrorCallback : ADC error callback
+ (+) InjectedConvCpltCallback : ADC group injected conversion complete callback
+ (+) InjectedQueueOverflowCallback : ADC group injected context queue overflow callback
+ (+) LevelOutOfWindow2Callback : ADC analog watchdog 2 callback
+ (+) LevelOutOfWindow3Callback : ADC analog watchdog 3 callback
+ (+) EndOfSamplingCallback : ADC end of sampling callback
+ (+) MspInitCallback : ADC Msp Init callback
+ (+) MspDeInitCallback : ADC Msp DeInit callback
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+ [..]
+
+ Use function @ref HAL_ADC_UnRegisterCallback to reset a callback to the default
+ weak function.
+ [..]
+
+ @ref HAL_ADC_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) ConvCpltCallback : ADC conversion complete callback
+ (+) ConvHalfCpltCallback : ADC conversion DMA half-transfer callback
+ (+) LevelOutOfWindowCallback : ADC analog watchdog 1 callback
+ (+) ErrorCallback : ADC error callback
+ (+) InjectedConvCpltCallback : ADC group injected conversion complete callback
+ (+) InjectedQueueOverflowCallback : ADC group injected context queue overflow callback
+ (+) LevelOutOfWindow2Callback : ADC analog watchdog 2 callback
+ (+) LevelOutOfWindow3Callback : ADC analog watchdog 3 callback
+ (+) EndOfSamplingCallback : ADC end of sampling callback
+ (+) MspInitCallback : ADC Msp Init callback
+ (+) MspDeInitCallback : ADC Msp DeInit callback
+ [..]
+
+ By default, after the @ref HAL_ADC_Init() and when the state is @ref HAL_ADC_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples @ref HAL_ADC_ConvCpltCallback(), @ref HAL_ADC_ErrorCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the @ref HAL_ADC_Init()/ @ref HAL_ADC_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ [..]
+
+ If MspInit or MspDeInit are not null, the @ref HAL_ADC_Init()/ @ref HAL_ADC_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+ [..]
+
+ Callbacks can be registered/unregistered in @ref HAL_ADC_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in @ref HAL_ADC_STATE_READY or @ref HAL_ADC_STATE_RESET state,
+ thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
+ [..]
+
+ Then, the user first registers the MspInit/MspDeInit user callbacks
+ using @ref HAL_ADC_RegisterCallback() before calling @ref HAL_ADC_DeInit()
+ or @ref HAL_ADC_Init() function.
+ [..]
+
+ When the compilation flag USE_HAL_ADC_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available and all callbacks
+ are set to the corresponding weak functions.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup ADC ADC
+ * @brief ADC HAL module driver
+ * @{
+ */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup ADC_Private_Constants ADC Private Constants
+ * @{
+ */
+#define ADC_CFGR_FIELDS_1 ((uint32_t)(ADC_CFGR_RES |\
+ ADC_CFGR_CONT | ADC_CFGR_OVRMOD |\
+ ADC_CFGR_DISCEN | ADC_CFGR_DISCNUM |\
+ ADC_CFGR_EXTEN | ADC_CFGR_EXTSEL)) /*!< ADC_CFGR fields of parameters that can be updated
+ when no regular conversion is on-going */
+
+#define ADC_CFGR2_FIELDS ((uint32_t)(ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR |\
+ ADC_CFGR2_OVSS | ADC_CFGR2_TROVS |\
+ ADC_CFGR2_ROVSM)) /*!< ADC_CFGR2 fields of parameters that can be updated when no conversion
+ (neither regular nor injected) is on-going */
+
+/* Timeout values for ADC operations (enable settling time, */
+/* disable settling time, ...). */
+/* Values defined to be higher than worst cases: low clock frequency, */
+/* maximum prescalers. */
+#define ADC_ENABLE_TIMEOUT (2UL) /*!< ADC enable time-out value */
+#define ADC_DISABLE_TIMEOUT (2UL) /*!< ADC disable time-out value */
+
+/* Timeout to wait for current conversion on going to be completed. */
+/* Timeout fixed to worst case, for 1 channel. */
+/* - maximum sampling time (830.5 adc_clk) */
+/* - ADC resolution (Tsar 16 bits= 16.5 adc_clk) */
+/* - ADC clock with prescaler 256 */
+/* 823 * 256 = 210688 clock cycles max */
+/* Unit: cycles of CPU clock. */
+#define ADC_CONVERSION_TIME_MAX_CPU_CYCLES ((uint32_t) 210688) /*!< ADC conversion completion time-out value */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup ADC_Exported_Functions ADC Exported Functions
+ * @{
+ */
+
+/** @defgroup ADC_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief ADC Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the ADC.
+ (+) De-initialize the ADC.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the ADC peripheral and regular group according to
+ * parameters specified in structure "ADC_InitTypeDef".
+ * @note As prerequisite, ADC clock must be configured at RCC top level
+ * (refer to description of RCC configuration for ADC
+ * in header of this file).
+ * @note Possibility to update parameters on the fly:
+ * This function initializes the ADC MSP (HAL_ADC_MspInit()) only when
+ * coming from ADC state reset. Following calls to this function can
+ * be used to reconfigure some parameters of ADC_InitTypeDef
+ * structure on the fly, without modifying MSP configuration. If ADC
+ * MSP has to be modified again, HAL_ADC_DeInit() must be called
+ * before HAL_ADC_Init().
+ * The setting of these parameters is conditioned to ADC state.
+ * For parameters constraints, see comments of structure
+ * "ADC_InitTypeDef".
+ * @note This function configures the ADC within 2 scopes: scope of entire
+ * ADC and scope of regular group. For parameters details, see comments
+ * of structure "ADC_InitTypeDef".
+ * @note Parameters related to common ADC registers (ADC clock mode) are set
+ * only if all ADCs are disabled.
+ * If this is not the case, these common parameters setting are
+ * bypassed without error reporting: it can be the intended behaviour in
+ * case of update of a parameter of ADC_InitTypeDef on the fly,
+ * without disabling the other ADCs.
+ * @param hadc ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ uint32_t tmpCFGR;
+ uint32_t tmp_adc_reg_is_conversion_on_going;
+ __IO uint32_t wait_loop_index = 0UL;
+ uint32_t tmp_adc_is_conversion_on_going_regular;
+ uint32_t tmp_adc_is_conversion_on_going_injected;
+
+ /* Check ADC handle */
+ if (hadc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_CLOCKPRESCALER(hadc->Init.ClockPrescaler));
+ assert_param(IS_ADC_RESOLUTION(hadc->Init.Resolution));
+ assert_param(IS_ADC_SCAN_MODE(hadc->Init.ScanConvMode));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_EXTTRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
+ assert_param(IS_ADC_EXTTRIG(hadc->Init.ExternalTrigConv));
+ assert_param(IS_ADC_CONVERSIONDATAMGT(hadc->Init.ConversionDataManagement));
+ assert_param(IS_ADC_EOC_SELECTION(hadc->Init.EOCSelection));
+ assert_param(IS_ADC_OVERRUN(hadc->Init.Overrun));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.LowPowerAutoWait));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.OversamplingMode));
+
+ if (hadc->Init.ScanConvMode != ADC_SCAN_DISABLE)
+ {
+ assert_param(IS_ADC_REGULAR_NB_CONV(hadc->Init.NbrOfConversion));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DiscontinuousConvMode));
+
+ if (hadc->Init.DiscontinuousConvMode == ENABLE)
+ {
+ assert_param(IS_ADC_REGULAR_DISCONT_NUMBER(hadc->Init.NbrOfDiscConversion));
+ }
+ }
+
+ /* DISCEN and CONT bits cannot be set at the same time */
+ assert_param(!((hadc->Init.DiscontinuousConvMode == ENABLE) && (hadc->Init.ContinuousConvMode == ENABLE)));
+
+ /* Actions performed only if ADC is coming from state reset: */
+ /* - Initialization of ADC MSP */
+ if (hadc->State == HAL_ADC_STATE_RESET)
+ {
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ /* Init the ADC Callback settings */
+ hadc->ConvCpltCallback = HAL_ADC_ConvCpltCallback; /* Legacy weak callback */
+ hadc->ConvHalfCpltCallback = HAL_ADC_ConvHalfCpltCallback; /* Legacy weak callback */
+ hadc->LevelOutOfWindowCallback = HAL_ADC_LevelOutOfWindowCallback; /* Legacy weak callback */
+ hadc->ErrorCallback = HAL_ADC_ErrorCallback; /* Legacy weak callback */
+ hadc->InjectedConvCpltCallback = HAL_ADCEx_InjectedConvCpltCallback; /* Legacy weak callback */
+ hadc->InjectedQueueOverflowCallback = HAL_ADCEx_InjectedQueueOverflowCallback; /* Legacy weak callback */
+ hadc->LevelOutOfWindow2Callback = HAL_ADCEx_LevelOutOfWindow2Callback; /* Legacy weak callback */
+ hadc->LevelOutOfWindow3Callback = HAL_ADCEx_LevelOutOfWindow3Callback; /* Legacy weak callback */
+ hadc->EndOfSamplingCallback = HAL_ADCEx_EndOfSamplingCallback; /* Legacy weak callback */
+
+ if (hadc->MspInitCallback == NULL)
+ {
+ hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware */
+ hadc->MspInitCallback(hadc);
+#else
+ /* Init the low level hardware */
+ HAL_ADC_MspInit(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+
+ /* Initialize Lock */
+ hadc->Lock = HAL_UNLOCKED;
+ }
+
+ /* - Exit from deep-power-down mode and ADC voltage regulator enable */
+ if (LL_ADC_IsDeepPowerDownEnabled(hadc->Instance) != 0UL)
+ {
+ /* Disable ADC deep power down mode */
+ LL_ADC_DisableDeepPowerDown(hadc->Instance);
+
+ /* System was in deep power down mode, calibration must
+ be relaunched or a previously saved calibration factor
+ re-applied once the ADC voltage regulator is enabled */
+ }
+
+ if (LL_ADC_IsInternalRegulatorEnabled(hadc->Instance) == 0UL)
+ {
+ /* Enable ADC internal voltage regulator */
+ LL_ADC_EnableInternalRegulator(hadc->Instance);
+
+ /* Note: Variable divided by 2 to compensate partially */
+ /* CPU processing cycles, scaling in us split to not */
+ /* exceed 32 bits register capacity and handle low frequency. */
+ wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US / 10UL) * (SystemCoreClock / (100000UL * 2UL)));
+ while (wait_loop_index != 0UL)
+ {
+ wait_loop_index--;
+ }
+ }
+
+ /* Verification that ADC voltage regulator is correctly enabled, whether */
+ /* or not ADC is coming from state reset (if any potential problem of */
+ /* clocking, voltage regulator would not be enabled). */
+ if (LL_ADC_IsInternalRegulatorEnabled(hadc->Instance) == 0UL)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ /* Configuration of ADC parameters if previous preliminary actions are */
+ /* correctly completed and if there is no conversion on going on regular */
+ /* group (ADC may already be enabled at this point if HAL_ADC_Init() is */
+ /* called to update a parameter on the fly). */
+ tmp_adc_reg_is_conversion_on_going = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+
+ if (((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) == 0UL)
+ && (tmp_adc_reg_is_conversion_on_going == 0UL)
+ )
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY,
+ HAL_ADC_STATE_BUSY_INTERNAL);
+
+ /* Configuration of common ADC parameters */
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated only when ADC is disabled: */
+ /* - clock configuration */
+ if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+ {
+ if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+ {
+ /* Reset configuration of ADC common register CCR: */
+ /* */
+ /* - ADC clock mode and ACC prescaler (CKMODE and PRESC bits)are set */
+ /* according to adc->Init.ClockPrescaler. It selects the clock */
+ /* source and sets the clock division factor. */
+ /* */
+ /* Some parameters of this register are not reset, since they are set */
+ /* by other functions and must be kept in case of usage of this */
+ /* function on the fly (update of a parameter of ADC_InitTypeDef */
+ /* without needing to reconfigure all other ADC groups/channels */
+ /* parameters): */
+ /* - when multimode feature is available, multimode-related */
+ /* parameters: MDMA, DMACFG, DELAY, DUAL (set by API */
+ /* HAL_ADCEx_MultiModeConfigChannel() ) */
+ /* - internal measurement paths: Vbat, temperature sensor, Vref */
+ /* (set into HAL_ADC_ConfigChannel() or */
+ /* HAL_ADCEx_InjectedConfigChannel() ) */
+ LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(hadc->Instance), hadc->Init.ClockPrescaler);
+ }
+ }
+
+ /* Configuration of ADC: */
+ /* - resolution Init.Resolution */
+ /* - external trigger to start conversion Init.ExternalTrigConv */
+ /* - external trigger polarity Init.ExternalTrigConvEdge */
+ /* - continuous conversion mode Init.ContinuousConvMode */
+ /* - overrun Init.Overrun */
+ /* - discontinuous mode Init.DiscontinuousConvMode */
+ /* - discontinuous mode channel count Init.NbrOfDiscConversion */
+#if defined(ADC_VER_V5_3)
+ tmpCFGR = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode) |
+ hadc->Init.Overrun |
+ hadc->Init.Resolution |
+ ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode) );
+
+#else
+ if((HAL_GetREVID() > REV_ID_Y) && (ADC_RESOLUTION_8B == hadc->Init.Resolution))
+ {
+ /* for STM32H7 silicon rev.B and above , ADC_CFGR_RES value for 8bits resolution is : b111 */
+ tmpCFGR = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode) |
+ hadc->Init.Overrun |
+ hadc->Init.Resolution |(ADC_CFGR_RES_1|ADC_CFGR_RES_0) |
+ ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode) );
+ }
+ else
+ {
+ tmpCFGR = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode) |
+ hadc->Init.Overrun |
+ hadc->Init.Resolution |
+ ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode) );
+ }
+
+#endif /* ADC_VER_V5_3 */
+
+ if (hadc->Init.DiscontinuousConvMode == ENABLE)
+ {
+ tmpCFGR |= ADC_CFGR_DISCONTINUOUS_NUM(hadc->Init.NbrOfDiscConversion);
+ }
+
+ /* Enable external trigger if trigger selection is different of software */
+ /* start. */
+ /* Note: This configuration keeps the hardware feature of parameter */
+ /* ExternalTrigConvEdge "trigger edge none" equivalent to */
+ /* software start. */
+ if (hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
+ {
+ tmpCFGR |= ((hadc->Init.ExternalTrigConv & ADC_CFGR_EXTSEL)
+ | hadc->Init.ExternalTrigConvEdge
+ );
+ }
+
+ /* Update Configuration Register CFGR */
+ MODIFY_REG(hadc->Instance->CFGR, ADC_CFGR_FIELDS_1, tmpCFGR);
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated when ADC is disabled or enabled without */
+ /* conversion on going on regular and injected groups: */
+ /* - Conversion data management Init.ConversionDataManagement */
+ /* - LowPowerAutoWait feature Init.LowPowerAutoWait */
+ /* - Oversampling parameters Init.Oversampling */
+ tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+ tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+ if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+ && (tmp_adc_is_conversion_on_going_injected == 0UL)
+ )
+ {
+ tmpCFGR = (
+ ADC_CFGR_AUTOWAIT((uint32_t)hadc->Init.LowPowerAutoWait) |
+ ADC_CFGR_DMACONTREQ((uint32_t)hadc->Init.ConversionDataManagement));
+
+ MODIFY_REG(hadc->Instance->CFGR, ADC_CFGR_FIELDS_2, tmpCFGR);
+
+ if (hadc->Init.OversamplingMode == ENABLE)
+ {
+ assert_param(IS_ADC_OVERSAMPLING_RATIO(hadc->Init.Oversampling.Ratio));
+ assert_param(IS_ADC_RIGHT_BIT_SHIFT(hadc->Init.Oversampling.RightBitShift));
+ assert_param(IS_ADC_TRIGGERED_OVERSAMPLING_MODE(hadc->Init.Oversampling.TriggeredMode));
+ assert_param(IS_ADC_REGOVERSAMPLING_MODE(hadc->Init.Oversampling.OversamplingStopReset));
+
+ if ((hadc->Init.ExternalTrigConv == ADC_SOFTWARE_START)
+ || (hadc->Init.ExternalTrigConvEdge == ADC_EXTERNALTRIGCONVEDGE_NONE))
+ {
+ /* Multi trigger is not applicable to software-triggered conversions */
+ assert_param((hadc->Init.Oversampling.TriggeredMode == ADC_TRIGGEREDMODE_SINGLE_TRIGGER));
+ }
+
+ /* Configuration of Oversampler: */
+ /* - Oversampling Ratio */
+ /* - Right bit shift */
+ /* - Left bit shift */
+ /* - Triggered mode */
+ /* - Oversampling mode (continued/resumed) */
+ MODIFY_REG(hadc->Instance->CFGR2, ADC_CFGR2_FIELDS,
+ ADC_CFGR2_ROVSE |
+ ((hadc->Init.Oversampling.Ratio - 1UL) << ADC_CFGR2_OVSR_Pos) |
+ hadc->Init.Oversampling.RightBitShift |
+ hadc->Init.Oversampling.TriggeredMode |
+ hadc->Init.Oversampling.OversamplingStopReset);
+
+ }
+ else
+ {
+ /* Disable ADC oversampling scope on ADC group regular */
+ CLEAR_BIT(hadc->Instance->CFGR2, ADC_CFGR2_ROVSE);
+ }
+
+ /* Set the LeftShift parameter: it is applied to the final result with or without oversampling */
+ MODIFY_REG(hadc->Instance->CFGR2, ADC_CFGR2_LSHIFT, hadc->Init.LeftBitShift);
+
+ /* Configure the BOOST Mode */
+ ADC_ConfigureBoostMode(hadc);
+ }
+
+ /* Configuration of regular group sequencer: */
+ /* - if scan mode is disabled, regular channels sequence length is set to */
+ /* 0x00: 1 channel converted (channel on regular rank 1) */
+ /* Parameter "NbrOfConversion" is discarded. */
+ /* Note: Scan mode is not present by hardware on this device, but */
+ /* emulated by software for alignment over all STM32 devices. */
+ /* - if scan mode is enabled, regular channels sequence length is set to */
+ /* parameter "NbrOfConversion". */
+
+ if (hadc->Init.ScanConvMode == ADC_SCAN_ENABLE)
+ {
+ /* Set number of ranks in regular group sequencer */
+ MODIFY_REG(hadc->Instance->SQR1, ADC_SQR1_L, (hadc->Init.NbrOfConversion - (uint8_t)1));
+ }
+ else
+ {
+ CLEAR_BIT(hadc->Instance->SQR1, ADC_SQR1_L);
+ }
+
+ /* Initialize the ADC state */
+ /* Clear HAL_ADC_STATE_BUSY_INTERNAL bit, set HAL_ADC_STATE_READY bit */
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_BUSY_INTERNAL, HAL_ADC_STATE_READY);
+ }
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Deinitialize the ADC peripheral registers to their default reset
+ * values, with deinitialization of the ADC MSP.
+ * @note For devices with several ADCs: reset of ADC common registers is done
+ * only if all ADCs sharing the same common group are disabled.
+ * (function "HAL_ADC_MspDeInit()" is also called under the same conditions:
+ * all ADC instances use the same core clock at RCC level, disabling
+ * the core clock reset all ADC instances).
+ * If this is not the case, reset of these common parameters reset is
+ * bypassed without error reporting: it can be the intended behavior in
+ * case of reset of a single ADC while the other ADCs sharing the same
+ * common group is still running.
+ * @note By default, HAL_ADC_DeInit() set ADC in mode deep power-down:
+ * this saves more power by reducing leakage currents
+ * and is particularly interesting before entering MCU low-power modes.
+ * @param hadc ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check ADC handle */
+ if (hadc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_BUSY_INTERNAL);
+
+ /* Stop potential conversion on going */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ /* Flush register JSQR: reset the queue sequencer when injected */
+ /* queue sequencer is enabled and ADC disabled. */
+ /* The software and hardware triggers of the injected sequence are both */
+ /* internally disabled just after the completion of the last valid */
+ /* injected sequence. */
+ SET_BIT(hadc->Instance->CFGR, ADC_CFGR_JQM);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Disable the ADC peripheral */
+ tmp_hal_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_READY;
+ }
+ }
+
+ /* Note: HAL ADC deInit is done independently of ADC conversion stop */
+ /* and disable return status. In case of status fail, attempt to */
+ /* perform deinitialization anyway and it is up user code in */
+ /* in HAL_ADC_MspDeInit() to reset the ADC peripheral using */
+ /* system RCC hard reset. */
+
+ /* ========== Reset ADC registers ========== */
+ /* Reset register IER */
+ __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_AWD3 | ADC_IT_AWD2 | ADC_IT_AWD1 |
+ ADC_IT_JQOVF | ADC_IT_OVR |
+ ADC_IT_JEOS | ADC_IT_JEOC |
+ ADC_IT_EOS | ADC_IT_EOC |
+ ADC_IT_EOSMP | ADC_IT_RDY));
+
+ /* Reset register ISR */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_AWD3 | ADC_FLAG_AWD2 | ADC_FLAG_AWD1 |
+ ADC_FLAG_JQOVF | ADC_FLAG_OVR |
+ ADC_FLAG_JEOS | ADC_FLAG_JEOC |
+ ADC_FLAG_EOS | ADC_FLAG_EOC |
+ ADC_FLAG_EOSMP | ADC_FLAG_RDY));
+
+ /* Reset register CR */
+ /* Bits ADC_CR_JADSTP, ADC_CR_ADSTP, ADC_CR_JADSTART, ADC_CR_ADSTART,
+ ADC_CR_ADCAL, ADC_CR_ADDIS and ADC_CR_ADEN are in access mode "read-set":
+ no direct reset applicable.
+ Update CR register to reset value where doable by software */
+ CLEAR_BIT(hadc->Instance->CR, ADC_CR_ADVREGEN | ADC_CR_ADCALDIF);
+ SET_BIT(hadc->Instance->CR, ADC_CR_DEEPPWD);
+
+ /* Reset register CFGR */
+ CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_AWD1CH | ADC_CFGR_JAUTO | ADC_CFGR_JAWD1EN |
+ ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL | ADC_CFGR_JQM |
+ ADC_CFGR_JDISCEN | ADC_CFGR_DISCNUM | ADC_CFGR_DISCEN |
+ ADC_CFGR_AUTDLY | ADC_CFGR_CONT | ADC_CFGR_OVRMOD |
+ ADC_CFGR_EXTEN | ADC_CFGR_EXTSEL |
+ ADC_CFGR_RES | ADC_CFGR_DMNGT);
+ SET_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS);
+
+ /* Reset register CFGR2 */
+ CLEAR_BIT(hadc->Instance->CFGR2, ADC_CFGR2_ROVSM | ADC_CFGR2_TROVS | ADC_CFGR2_OVSS |
+ ADC_CFGR2_OVSR | ADC_CFGR2_JOVSE | ADC_CFGR2_ROVSE);
+
+ /* Reset register SMPR1 */
+ CLEAR_BIT(hadc->Instance->SMPR1, ADC_SMPR1_FIELDS);
+
+ /* Reset register SMPR2 */
+ CLEAR_BIT(hadc->Instance->SMPR2, ADC_SMPR2_SMP18 | ADC_SMPR2_SMP17 | ADC_SMPR2_SMP16 |
+ ADC_SMPR2_SMP15 | ADC_SMPR2_SMP14 | ADC_SMPR2_SMP13 |
+ ADC_SMPR2_SMP12 | ADC_SMPR2_SMP11 | ADC_SMPR2_SMP10);
+
+ /* Reset register LTR1 and HTR1 */
+ CLEAR_BIT(hadc->Instance->LTR1, ADC_LTR_LT);
+ CLEAR_BIT(hadc->Instance->HTR1, ADC_HTR_HT);
+
+ /* Reset register LTR2 and HTR2*/
+ CLEAR_BIT(hadc->Instance->LTR2, ADC_LTR_LT);
+ CLEAR_BIT(hadc->Instance->HTR2, ADC_HTR_HT);
+
+ /* Reset register LTR3 and HTR3 */
+ CLEAR_BIT(hadc->Instance->LTR3, ADC_LTR_LT);
+ CLEAR_BIT(hadc->Instance->HTR3, ADC_HTR_HT);
+
+ /* Reset register SQR1 */
+ CLEAR_BIT(hadc->Instance->SQR1, ADC_SQR1_SQ4 | ADC_SQR1_SQ3 | ADC_SQR1_SQ2 |
+ ADC_SQR1_SQ1 | ADC_SQR1_L);
+
+ /* Reset register SQR2 */
+ CLEAR_BIT(hadc->Instance->SQR2, ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7 |
+ ADC_SQR2_SQ6 | ADC_SQR2_SQ5);
+
+ /* Reset register SQR3 */
+ CLEAR_BIT(hadc->Instance->SQR3, ADC_SQR3_SQ14 | ADC_SQR3_SQ13 | ADC_SQR3_SQ12 |
+ ADC_SQR3_SQ11 | ADC_SQR3_SQ10);
+
+ /* Reset register SQR4 */
+ CLEAR_BIT(hadc->Instance->SQR4, ADC_SQR4_SQ16 | ADC_SQR4_SQ15);
+
+ /* Register JSQR was reset when the ADC was disabled */
+
+ /* Reset register DR */
+ /* bits in access mode read only, no direct reset applicable*/
+
+ /* Reset register OFR1 */
+ CLEAR_BIT(hadc->Instance->OFR1, ADC_OFR1_SSATE | ADC_OFR1_OFFSET1_CH | ADC_OFR1_OFFSET1);
+ /* Reset register OFR2 */
+ CLEAR_BIT(hadc->Instance->OFR2, ADC_OFR2_SSATE | ADC_OFR2_OFFSET2_CH | ADC_OFR2_OFFSET2);
+ /* Reset register OFR3 */
+ CLEAR_BIT(hadc->Instance->OFR3, ADC_OFR3_SSATE | ADC_OFR3_OFFSET3_CH | ADC_OFR3_OFFSET3);
+ /* Reset register OFR4 */
+ CLEAR_BIT(hadc->Instance->OFR4, ADC_OFR4_SSATE | ADC_OFR4_OFFSET4_CH | ADC_OFR4_OFFSET4);
+
+ /* Reset registers JDR1, JDR2, JDR3, JDR4 */
+ /* bits in access mode read only, no direct reset applicable*/
+
+ /* Reset register AWD2CR */
+ CLEAR_BIT(hadc->Instance->AWD2CR, ADC_AWD2CR_AWD2CH);
+
+ /* Reset register AWD3CR */
+ CLEAR_BIT(hadc->Instance->AWD3CR, ADC_AWD3CR_AWD3CH);
+
+ /* Reset register DIFSEL */
+ CLEAR_BIT(hadc->Instance->DIFSEL, ADC_DIFSEL_DIFSEL);
+
+ /* Reset register CALFACT */
+ CLEAR_BIT(hadc->Instance->CALFACT, ADC_CALFACT_CALFACT_D | ADC_CALFACT_CALFACT_S);
+
+
+ /* ========== Reset common ADC registers ========== */
+
+ /* Software is allowed to change common parameters only when all the other
+ ADCs are disabled. */
+ if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+ {
+ /* Reset configuration of ADC common register CCR:
+ - clock mode: CKMODE, PRESCEN
+ - multimode related parameters(when this feature is available): DELAY, DUAL
+ (set into HAL_ADCEx_MultiModeConfigChannel() API)
+ - internal measurement paths: Vbat, temperature sensor, Vref (set into
+ HAL_ADC_ConfigChannel() or HAL_ADCEx_InjectedConfigChannel() )
+ */
+ ADC_CLEAR_COMMON_CONTROL_REGISTER(hadc);
+ }
+
+ /* DeInit the low level hardware.
+
+ For example:
+ __HAL_RCC_ADC_FORCE_RESET();
+ __HAL_RCC_ADC_RELEASE_RESET();
+ __HAL_RCC_ADC_CLK_DISABLE();
+
+ Keep in mind that all ADCs use the same clock: disabling
+ the clock will reset all ADCs.
+
+ */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ if (hadc->MspDeInitCallback == NULL)
+ {
+ hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: RCC clock, NVIC */
+ hadc->MspDeInitCallback(hadc);
+#else
+ /* DeInit the low level hardware: RCC clock, NVIC */
+ HAL_ADC_MspDeInit(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+
+ /* Reset injected channel configuration parameters */
+ hadc->InjectionConfig.ContextQueue = 0;
+ hadc->InjectionConfig.ChannelCount = 0;
+
+ /* Set ADC state */
+ hadc->State = HAL_ADC_STATE_RESET;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Initialize the ADC MSP.
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADC_MspInit must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief DeInitialize the ADC MSP.
+ * @param hadc ADC handle
+ * @note All ADC instances use the same core clock at RCC level, disabling
+ * the core clock reset all ADC instances).
+ * @retval None
+ */
+__weak void HAL_ADC_MspDeInit(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADC_MspDeInit must be implemented in the user file.
+ */
+}
+
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User ADC Callback
+ * To be used instead of the weak predefined callback
+ * @param hadc Pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_ADC_CONVERSION_COMPLETE_CB_ID ADC conversion complete callback ID
+ * @arg @ref HAL_ADC_CONVERSION_HALF_CB_ID ADC conversion DMA half-transfer callback ID
+ * @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID ADC analog watchdog 1 callback ID
+ * @arg @ref HAL_ADC_ERROR_CB_ID ADC error callback ID
+ * @arg @ref HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID ADC group injected conversion complete callback ID
+ * @arg @ref HAL_ADC_INJ_QUEUE_OVEFLOW_CB_ID ADC group injected context queue overflow callback ID
+ * @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_2_CB_ID ADC analog watchdog 2 callback ID
+ * @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_3_CB_ID ADC analog watchdog 3 callback ID
+ * @arg @ref HAL_ADC_END_OF_SAMPLING_CB_ID ADC end of sampling callback ID
+ * @arg @ref HAL_ADC_MSPINIT_CB_ID ADC Msp Init callback ID
+ * @arg @ref HAL_ADC_MSPDEINIT_CB_ID ADC Msp DeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_RegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID, pADC_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ if ((hadc->State & HAL_ADC_STATE_READY) != 0UL)
+ {
+ switch (CallbackID)
+ {
+ case HAL_ADC_CONVERSION_COMPLETE_CB_ID :
+ hadc->ConvCpltCallback = pCallback;
+ break;
+
+ case HAL_ADC_CONVERSION_HALF_CB_ID :
+ hadc->ConvHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID :
+ hadc->LevelOutOfWindowCallback = pCallback;
+ break;
+
+ case HAL_ADC_ERROR_CB_ID :
+ hadc->ErrorCallback = pCallback;
+ break;
+
+ case HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID :
+ hadc->InjectedConvCpltCallback = pCallback;
+ break;
+
+ case HAL_ADC_INJ_QUEUE_OVEFLOW_CB_ID :
+ hadc->InjectedQueueOverflowCallback = pCallback;
+ break;
+
+ case HAL_ADC_LEVEL_OUT_OF_WINDOW_2_CB_ID :
+ hadc->LevelOutOfWindow2Callback = pCallback;
+ break;
+
+ case HAL_ADC_LEVEL_OUT_OF_WINDOW_3_CB_ID :
+ hadc->LevelOutOfWindow3Callback = pCallback;
+ break;
+
+ case HAL_ADC_END_OF_SAMPLING_CB_ID :
+ hadc->EndOfSamplingCallback = pCallback;
+ break;
+
+ case HAL_ADC_MSPINIT_CB_ID :
+ hadc->MspInitCallback = pCallback;
+ break;
+
+ case HAL_ADC_MSPDEINIT_CB_ID :
+ hadc->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_ADC_STATE_RESET == hadc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_ADC_MSPINIT_CB_ID :
+ hadc->MspInitCallback = pCallback;
+ break;
+
+ case HAL_ADC_MSPDEINIT_CB_ID :
+ hadc->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a ADC Callback
+ * ADC callback is redirected to the weak predefined callback
+ * @param hadc Pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_ADC_CONVERSION_COMPLETE_CB_ID ADC conversion complete callback ID
+ * @arg @ref HAL_ADC_CONVERSION_HALF_CB_ID ADC conversion DMA half-transfer callback ID
+ * @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID ADC analog watchdog 1 callback ID
+ * @arg @ref HAL_ADC_ERROR_CB_ID ADC error callback ID
+ * @arg @ref HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID ADC group injected conversion complete callback ID
+ * @arg @ref HAL_ADC_INJ_QUEUE_OVEFLOW_CB_ID ADC group injected context queue overflow callback ID
+ * @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_2_CB_ID ADC analog watchdog 2 callback ID
+ * @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_3_CB_ID ADC analog watchdog 3 callback ID
+ * @arg @ref HAL_ADC_END_OF_SAMPLING_CB_ID ADC end of sampling callback ID
+ * @arg @ref HAL_ADC_MSPINIT_CB_ID ADC Msp Init callback ID
+ * @arg @ref HAL_ADC_MSPDEINIT_CB_ID ADC Msp DeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_UnRegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if ((hadc->State & HAL_ADC_STATE_READY) != 0UL)
+ {
+ switch (CallbackID)
+ {
+ case HAL_ADC_CONVERSION_COMPLETE_CB_ID :
+ hadc->ConvCpltCallback = HAL_ADC_ConvCpltCallback;
+ break;
+
+ case HAL_ADC_CONVERSION_HALF_CB_ID :
+ hadc->ConvHalfCpltCallback = HAL_ADC_ConvHalfCpltCallback;
+ break;
+
+ case HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID :
+ hadc->LevelOutOfWindowCallback = HAL_ADC_LevelOutOfWindowCallback;
+ break;
+
+ case HAL_ADC_ERROR_CB_ID :
+ hadc->ErrorCallback = HAL_ADC_ErrorCallback;
+ break;
+
+ case HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID :
+ hadc->InjectedConvCpltCallback = HAL_ADCEx_InjectedConvCpltCallback;
+ break;
+
+ case HAL_ADC_INJ_QUEUE_OVEFLOW_CB_ID :
+ hadc->InjectedQueueOverflowCallback = HAL_ADCEx_InjectedQueueOverflowCallback;
+ break;
+
+ case HAL_ADC_LEVEL_OUT_OF_WINDOW_2_CB_ID :
+ hadc->LevelOutOfWindow2Callback = HAL_ADCEx_LevelOutOfWindow2Callback;
+ break;
+
+ case HAL_ADC_LEVEL_OUT_OF_WINDOW_3_CB_ID :
+ hadc->LevelOutOfWindow3Callback = HAL_ADCEx_LevelOutOfWindow3Callback;
+ break;
+
+ case HAL_ADC_END_OF_SAMPLING_CB_ID :
+ hadc->EndOfSamplingCallback = HAL_ADCEx_EndOfSamplingCallback;
+ break;
+
+ case HAL_ADC_MSPINIT_CB_ID :
+ hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_ADC_MSPDEINIT_CB_ID :
+ hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_ADC_STATE_RESET == hadc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_ADC_MSPINIT_CB_ID :
+ hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_ADC_MSPDEINIT_CB_ID :
+ hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Exported_Functions_Group2 ADC Input and Output operation functions
+ * @brief ADC IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start conversion of regular group.
+ (+) Stop conversion of regular group.
+ (+) Poll for conversion complete on regular group.
+ (+) Poll for conversion event.
+ (+) Get result of regular channel conversion.
+ (+) Start conversion of regular group and enable interruptions.
+ (+) Stop conversion of regular group and disable interruptions.
+ (+) Handle ADC interrupt request
+ (+) Start conversion of regular group and enable DMA transfer.
+ (+) Stop conversion of regular group and disable ADC DMA transfer.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable ADC, start conversion of regular group.
+ * @note Interruptions enabled in this function: None.
+ * @note Case of multimode enabled (when multimode feature is available):
+ * if ADC is Slave, ADC is enabled but conversion is not started,
+ * if ADC is master, ADC is enabled and multimode conversion is started.
+ * @param hadc ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ const ADC_TypeDef *tmpADC_Master;
+ uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Perform ADC enable and conversion start if no conversion is on going */
+ if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_hal_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ /* - Clear state bitfield related to regular group conversion results */
+ /* - Set state bitfield related to regular operation */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
+ HAL_ADC_STATE_REG_BUSY);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - if ADC instance is master or if multimode feature is not available
+ - if multimode setting is disabled (ADC instance slave in independent mode) */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ )
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* Set ADC error code */
+ /* Check if a conversion is on going on ADC group injected */
+ if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ /* Reset ADC error code fields related to regular conversions only */
+ CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
+ }
+ else
+ {
+ /* Reset all ADC error code fields */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Clear ADC group regular conversion flag and overrun flag */
+ /* (To ensure of no unknown state from potential previous ADC operations) */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS | ADC_FLAG_OVR));
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* Enable conversion of regular group. */
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ /* Case of multimode enabled (when multimode feature is available): */
+ /* - if ADC is slave and dual regular conversions are enabled, ADC is */
+ /* enabled only (conversion is not started), */
+ /* - if ADC is master, ADC is enabled and conversion is started. */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_ALTERN)
+ )
+ {
+ /* ADC instance is not a multimode slave instance with multimode regular conversions enabled */
+ if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO) != 0UL)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+
+ /* Start ADC group regular conversion */
+ LL_ADC_REG_StartConversion(hadc->Instance);
+ }
+ else
+ {
+ /* ADC instance is a multimode slave instance with multimode regular conversions enabled */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ /* if Master ADC JAUTO bit is set, update Slave State in setting
+ HAL_ADC_STATE_INJ_BUSY bit and in resetting HAL_ADC_STATE_INJ_EOC bit */
+ tmpADC_Master = __LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance);
+ if (READ_BIT(tmpADC_Master->CFGR, ADC_CFGR_JAUTO) != 0UL)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+ }
+ else
+ {
+ tmp_hal_status = HAL_BUSY;
+ }
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Stop ADC conversion of regular group (and injected channels in
+ * case of auto_injection mode), disable ADC peripheral.
+ * @note: ADC peripheral disable is forcing stop of potential
+ * conversion on injected group. If injected group is under use, it
+ * should be preliminarily stopped using HAL_ADCEx_InjectedStop function.
+ * @param hadc ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential conversion on going, on ADC groups regular and injected */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* 2. Disable the ADC peripheral */
+ tmp_hal_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Wait for regular group conversion to be completed.
+ * @note ADC conversion flags EOS (end of sequence) and EOC (end of
+ * conversion) are cleared by this function, with an exception:
+ * if low power feature "LowPowerAutoWait" is enabled, flags are
+ * not cleared to not interfere with this feature until data register
+ * is read using function HAL_ADC_GetValue().
+ * @note This function cannot be used in a particular setup: ADC configured
+ * in DMA mode and polling for end of each conversion (ADC init
+ * parameter "EOCSelection" set to ADC_EOC_SINGLE_CONV).
+ * In this case, DMA resets the flag EOC and polling cannot be
+ * performed on each conversion. Nevertheless, polling can still
+ * be performed on the complete sequence (ADC init
+ * parameter "EOCSelection" set to ADC_EOC_SEQ_CONV).
+ * @param hadc ADC handle
+ * @param Timeout Timeout value in millisecond.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t tmp_Flag_End;
+ uint32_t tmp_cfgr;
+ const ADC_TypeDef *tmpADC_Master;
+ uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* If end of conversion selected to end of sequence conversions */
+ if (hadc->Init.EOCSelection == ADC_EOC_SEQ_CONV)
+ {
+ tmp_Flag_End = ADC_FLAG_EOS;
+ }
+ /* If end of conversion selected to end of unitary conversion */
+ else /* ADC_EOC_SINGLE_CONV */
+ {
+ /* Verification that ADC configuration is compliant with polling for */
+ /* each conversion: */
+ /* Particular case is ADC configured in DMA mode and ADC sequencer with */
+ /* several ranks and polling for end of each conversion. */
+ /* For code simplicity sake, this particular case is generalized to */
+ /* ADC configured in DMA mode and and polling for end of each conversion. */
+ if ((tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_ALTERN)
+ )
+ {
+ /* Check DMNGT bit in handle ADC CFGR register */
+ if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_DMNGT_0) != 0UL)
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+ return HAL_ERROR;
+ }
+ else
+ {
+ tmp_Flag_End = (ADC_FLAG_EOC);
+ }
+ }
+ else
+ {
+ /* Check ADC DMA mode in multimode on ADC group regular */
+ if (LL_ADC_GetMultiDMATransfer(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) != LL_ADC_MULTI_REG_DMA_EACH_ADC)
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+ return HAL_ERROR;
+ }
+ else
+ {
+ tmp_Flag_End = (ADC_FLAG_EOC);
+ }
+ }
+ }
+
+ /* Get tick count */
+ tickstart = HAL_GetTick();
+
+ /* Wait until End of unitary conversion or sequence conversions flag is raised */
+ while ((hadc->Instance->ISR & tmp_Flag_End) == 0UL)
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+ {
+ /* Update ADC state machine to timeout */
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Update ADC state machine */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+
+ /* Determine whether any further conversion upcoming on group regular */
+ /* by external trigger, continuous mode or scan sequence on going. */
+ if ((LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL)
+ && (hadc->Init.ContinuousConvMode == DISABLE)
+ )
+ {
+ /* Check whether end of sequence is reached */
+ if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS))
+ {
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+ }
+
+ /* Get relevant register CFGR in ADC instance of ADC master or slave */
+ /* in function of multimode state (for devices with multimode */
+ /* available). */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_ALTERN)
+ )
+ {
+ /* Retrieve handle ADC CFGR register */
+ tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ /* Retrieve Master ADC CFGR register */
+ tmpADC_Master = __LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance);
+ tmp_cfgr = READ_REG(tmpADC_Master->CFGR);
+ }
+
+ /* Clear polled flag */
+ if (tmp_Flag_End == ADC_FLAG_EOS)
+ {
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOS);
+ }
+ else
+ {
+ /* Clear end of conversion EOC flag of regular group if low power feature */
+ /* "LowPowerAutoWait " is disabled, to not interfere with this feature */
+ /* until data register is read using function HAL_ADC_GetValue(). */
+ if (READ_BIT(tmp_cfgr, ADC_CFGR_AUTDLY) == 0UL)
+ {
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS));
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Poll for ADC event.
+ * @param hadc ADC handle
+ * @param EventType the ADC event type.
+ * This parameter can be one of the following values:
+ * @arg @ref ADC_EOSMP_EVENT ADC End of Sampling event
+ * @arg @ref ADC_AWD1_EVENT ADC Analog watchdog 1 event (main analog watchdog, present on all STM32 devices)
+ * @arg @ref ADC_AWD2_EVENT ADC Analog watchdog 2 event (additional analog watchdog, not present on all STM32 families)
+ * @arg @ref ADC_AWD3_EVENT ADC Analog watchdog 3 event (additional analog watchdog, not present on all STM32 families)
+ * @arg @ref ADC_OVR_EVENT ADC Overrun event
+ * @arg @ref ADC_JQOVF_EVENT ADC Injected context queue overflow event
+ * @param Timeout Timeout value in millisecond.
+ * @note The relevant flag is cleared if found to be set, except for ADC_FLAG_OVR.
+ * Indeed, the latter is reset only if hadc->Init.Overrun field is set
+ * to ADC_OVR_DATA_OVERWRITTEN. Otherwise, data register may be potentially overwritten
+ * by a new converted data as soon as OVR is cleared.
+ * To reset OVR flag once the preserved data is retrieved, the user can resort
+ * to macro __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef *hadc, uint32_t EventType, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_EVENT_TYPE(EventType));
+
+ /* Get tick count */
+ tickstart = HAL_GetTick();
+
+ /* Check selected event flag */
+ while (__HAL_ADC_GET_FLAG(hadc, EventType) == 0UL)
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+ {
+ /* Update ADC state machine to timeout */
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ switch (EventType)
+ {
+ /* End Of Sampling event */
+ case ADC_EOSMP_EVENT:
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOSMP);
+
+ /* Clear the End Of Sampling flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOSMP);
+
+ break;
+
+ /* Analog watchdog (level out of window) event */
+ /* Note: In case of several analog watchdog enabled, if needed to know */
+ /* which one triggered and on which ADCx, test ADC state of analog watchdog */
+ /* flags HAL_ADC_STATE_AWD1/2/3 using function "HAL_ADC_GetState()". */
+ /* For example: */
+ /* " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_AWD1) != 0UL) " */
+ /* " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_AWD2) != 0UL) " */
+ /* " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_AWD3) != 0UL) " */
+
+ /* Check analog watchdog 1 flag */
+ case ADC_AWD_EVENT:
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+
+ /* Clear ADC analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD1);
+
+ break;
+
+ /* Check analog watchdog 2 flag */
+ case ADC_AWD2_EVENT:
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD2);
+
+ /* Clear ADC analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD2);
+
+ break;
+
+ /* Check analog watchdog 3 flag */
+ case ADC_AWD3_EVENT:
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD3);
+
+ /* Clear ADC analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD3);
+
+ break;
+
+ /* Injected context queue overflow event */
+ case ADC_JQOVF_EVENT:
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_JQOVF);
+
+ /* Set ADC error code to Injected context queue overflow */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_JQOVF);
+
+ /* Clear ADC Injected context queue overflow flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JQOVF);
+
+ break;
+
+ /* Overrun event */
+ default: /* Case ADC_OVR_EVENT */
+ /* If overrun is set to overwrite previous data, overrun event is not */
+ /* considered as an error. */
+ /* (cf ref manual "Managing conversions without using the DMA and without */
+ /* overrun ") */
+ if (hadc->Init.Overrun == ADC_OVR_DATA_PRESERVED)
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_OVR);
+
+ /* Set ADC error code to overrun */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_OVR);
+ }
+ else
+ {
+ /* Clear ADC Overrun flag only if Overrun is set to ADC_OVR_DATA_OVERWRITTEN
+ otherwise, data register is potentially overwritten by new converted data as soon
+ as OVR is cleared. */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
+ }
+ break;
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable ADC, start conversion of regular group with interruption.
+ * @note Interruptions enabled in this function according to initialization
+ * setting : EOC (end of conversion), EOS (end of sequence),
+ * OVR overrun.
+ * Each of these interruptions has its dedicated callback function.
+ * @note Case of multimode enabled (when multimode feature is available):
+ * HAL_ADC_Start_IT() must be called for ADC Slave first, then for
+ * ADC Master.
+ * For ADC Slave, ADC is enabled only (conversion is not started).
+ * For ADC Master, ADC is enabled and multimode conversion is started.
+ * @note To guarantee a proper reset of all interruptions once all the needed
+ * conversions are obtained, HAL_ADC_Stop_IT() must be called to ensure
+ * a correct stop of the IT-based conversions.
+ * @note By default, HAL_ADC_Start_IT() does not enable the End Of Sampling
+ * interruption. If required (e.g. in case of oversampling with trigger
+ * mode), the user must:
+ * 1. first clear the EOSMP flag if set with macro __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOSMP)
+ * 2. then enable the EOSMP interrupt with macro __HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOSMP)
+ * before calling HAL_ADC_Start_IT().
+ * @param hadc ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ const ADC_TypeDef *tmpADC_Master;
+ uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Perform ADC enable and conversion start if no conversion is on going */
+ if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_hal_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ /* - Clear state bitfield related to regular group conversion results */
+ /* - Set state bitfield related to regular operation */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
+ HAL_ADC_STATE_REG_BUSY);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - if ADC instance is master or if multimode feature is not available
+ - if multimode setting is disabled (ADC instance slave in independent mode) */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ )
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* Set ADC error code */
+ /* Check if a conversion is on going on ADC group injected */
+ if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) != 0UL)
+ {
+ /* Reset ADC error code fields related to regular conversions only */
+ CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
+ }
+ else
+ {
+ /* Reset all ADC error code fields */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Clear ADC group regular conversion flag and overrun flag */
+ /* (To ensure of no unknown state from potential previous ADC operations) */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS | ADC_FLAG_OVR));
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* Disable all interruptions before enabling the desired ones */
+ __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_EOS | ADC_IT_OVR));
+
+ /* Enable ADC end of conversion interrupt */
+ switch (hadc->Init.EOCSelection)
+ {
+ case ADC_EOC_SEQ_CONV:
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOS);
+ break;
+ /* case ADC_EOC_SINGLE_CONV */
+ default:
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOC);
+ break;
+ }
+
+ /* Enable ADC overrun interrupt */
+ /* If hadc->Init.Overrun is set to ADC_OVR_DATA_PRESERVED, only then is
+ ADC_IT_OVR enabled; otherwise data overwrite is considered as normal
+ behavior and no CPU time is lost for a non-processed interruption */
+ if (hadc->Init.Overrun == ADC_OVR_DATA_PRESERVED)
+ {
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+ }
+
+ /* Enable conversion of regular group. */
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ /* Case of multimode enabled (when multimode feature is available): */
+ /* - if ADC is slave and dual regular conversions are enabled, ADC is */
+ /* enabled only (conversion is not started), */
+ /* - if ADC is master, ADC is enabled and conversion is started. */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_ALTERN)
+ )
+ {
+ /* ADC instance is not a multimode slave instance with multimode regular conversions enabled */
+ if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO) != 0UL)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+
+ /* Enable as well injected interruptions in case
+ HAL_ADCEx_InjectedStart_IT() has not been called beforehand. This
+ allows to start regular and injected conversions when JAUTO is
+ set with a single call to HAL_ADC_Start_IT() */
+ switch (hadc->Init.EOCSelection)
+ {
+ case ADC_EOC_SEQ_CONV:
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC);
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOS);
+ break;
+ /* case ADC_EOC_SINGLE_CONV */
+ default:
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOS);
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);
+ break;
+ }
+ }
+
+ /* Start ADC group regular conversion */
+ LL_ADC_REG_StartConversion(hadc->Instance);
+ }
+ else
+ {
+ /* ADC instance is a multimode slave instance with multimode regular conversions enabled */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ /* if Master ADC JAUTO bit is set, Slave injected interruptions
+ are enabled nevertheless (for same reason as above) */
+ tmpADC_Master = __LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance);
+ if (READ_BIT(tmpADC_Master->CFGR, ADC_CFGR_JAUTO) != 0UL)
+ {
+ /* First, update Slave State in setting HAL_ADC_STATE_INJ_BUSY bit
+ and in resetting HAL_ADC_STATE_INJ_EOC bit */
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ /* Next, set Slave injected interruptions */
+ switch (hadc->Init.EOCSelection)
+ {
+ case ADC_EOC_SEQ_CONV:
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC);
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOS);
+ break;
+ /* case ADC_EOC_SINGLE_CONV */
+ default:
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOS);
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ }
+ else
+ {
+ tmp_hal_status = HAL_BUSY;
+ }
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Stop ADC conversion of regular group (and injected group in
+ * case of auto_injection mode), disable interrution of
+ * end-of-conversion, disable ADC peripheral.
+ * @param hadc ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential conversion on going, on ADC groups regular and injected */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Disable ADC end of conversion interrupt for regular group */
+ /* Disable ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_EOS | ADC_IT_OVR));
+
+ /* 2. Disable the ADC peripheral */
+ tmp_hal_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Enable ADC, start conversion of regular group and transfer result through DMA.
+ * @note Interruptions enabled in this function:
+ * overrun (if applicable), DMA half transfer, DMA transfer complete.
+ * Each of these interruptions has its dedicated callback function.
+ * @note Case of multimode enabled (when multimode feature is available): HAL_ADC_Start_DMA()
+ * is designed for single-ADC mode only. For multimode, the dedicated
+ * HAL_ADCEx_MultiModeStart_DMA() function must be used.
+ * @param hadc ADC handle
+ * @param pData Destination Buffer address.
+ * @param Length Number of data to be transferred from ADC peripheral to memory
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Perform ADC enable and conversion start if no conversion is on going */
+ if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Ensure that multimode regular conversions are not enabled. */
+ /* Otherwise, dedicated API HAL_ADCEx_MultiModeStart_DMA() must be used. */
+ if ((tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_ALTERN)
+ )
+ {
+ /* Enable the ADC peripheral */
+ tmp_hal_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ /* - Clear state bitfield related to regular group conversion results */
+ /* - Set state bitfield related to regular operation */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
+ HAL_ADC_STATE_REG_BUSY);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - if ADC instance is master or if multimode feature is not available
+ - if multimode setting is disabled (ADC instance slave in independent mode) */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ )
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* Check if a conversion is on going on ADC group injected */
+ if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) != 0UL)
+ {
+ /* Reset ADC error code fields related to regular conversions only */
+ CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
+ }
+ else
+ {
+ /* Reset all ADC error code fields */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Set the DMA transfer complete callback */
+ hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;
+
+ /* Set the DMA half transfer complete callback */
+ hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt;
+
+ /* Set the DMA error callback */
+ hadc->DMA_Handle->XferErrorCallback = ADC_DMAError;
+
+
+ /* Manage ADC and DMA start: ADC overrun interruption, DMA start, */
+ /* ADC start (in case of SW start): */
+
+ /* Clear regular group conversion flag and overrun flag */
+ /* (To ensure of no unknown state from potential previous ADC */
+ /* operations) */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS | ADC_FLAG_OVR));
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* With DMA, overrun event is always considered as an error even if
+ hadc->Init.Overrun is set to ADC_OVR_DATA_OVERWRITTEN. Therefore,
+ ADC_IT_OVR is enabled. */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+
+ /* Enable ADC DMA mode*/
+ LL_ADC_REG_SetDataTransferMode(hadc->Instance, (uint32_t)hadc->Init.ConversionDataManagement);
+
+ /* Start the DMA channel */
+ tmp_hal_status = HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);
+
+ /* Enable conversion of regular group. */
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ /* Start ADC group regular conversion */
+ LL_ADC_REG_StartConversion(hadc->Instance);
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ }
+ else
+ {
+ tmp_hal_status = HAL_ERROR;
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+ }
+ else
+ {
+ tmp_hal_status = HAL_BUSY;
+ }
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Stop ADC conversion of regular group (and injected group in
+ * case of auto_injection mode), disable ADC DMA transfer, disable
+ * ADC peripheral.
+ * @note: ADC peripheral disable is forcing stop of potential
+ * conversion on ADC group injected. If ADC group injected is under use, it
+ * should be preliminarily stopped using HAL_ADCEx_InjectedStop function.
+ * @note Case of multimode enabled (when multimode feature is available):
+ * HAL_ADC_Stop_DMA() function is dedicated to single-ADC mode only.
+ * For multimode, the dedicated HAL_ADCEx_MultiModeStop_DMA() API must be used.
+ * @param hadc ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential ADC group regular conversion on going */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Disable ADC DMA (ADC DMA configuration of continous requests is kept) */
+ MODIFY_REG(hadc->Instance->CFGR, ADC_CFGR_DMNGT_0 |ADC_CFGR_DMNGT_1, 0UL);
+
+ /* Disable the DMA channel (in case of DMA in circular mode or stop */
+ /* while DMA transfer is on going) */
+ if (hadc->DMA_Handle->State == HAL_DMA_STATE_BUSY)
+ {
+ tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Check if DMA channel effectively disabled */
+ if (tmp_hal_status != HAL_OK)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+ }
+ }
+
+ /* Disable ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+
+ /* 2. Disable the ADC peripheral */
+ /* Update "tmp_hal_status" only if DMA channel disabling passed, */
+ /* to keep in memory a potential failing status. */
+ if (tmp_hal_status == HAL_OK)
+ {
+ tmp_hal_status = ADC_Disable(hadc);
+ }
+ else
+ {
+ (void)ADC_Disable(hadc);
+ }
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Get ADC regular group conversion result.
+ * @note Reading register DR automatically clears ADC flag EOC
+ * (ADC group regular end of unitary conversion).
+ * @note This function does not clear ADC flag EOS
+ * (ADC group regular end of sequence conversion).
+ * Occurrence of flag EOS rising:
+ * - If sequencer is composed of 1 rank, flag EOS is equivalent
+ * to flag EOC.
+ * - If sequencer is composed of several ranks, during the scan
+ * sequence flag EOC only is raised, at the end of the scan sequence
+ * both flags EOC and EOS are raised.
+ * To clear this flag, either use function:
+ * in programming model IT: @ref HAL_ADC_IRQHandler(), in programming
+ * model polling: @ref HAL_ADC_PollForConversion()
+ * or @ref __HAL_ADC_CLEAR_FLAG(&hadc, ADC_FLAG_EOS).
+ * @param hadc ADC handle
+ * @retval ADC group regular conversion data
+ */
+uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Note: EOC flag is not cleared here by software because automatically */
+ /* cleared by hardware when reading register DR. */
+
+ /* Return ADC converted value */
+ return hadc->Instance->DR;
+}
+
+/**
+ * @brief Handle ADC interrupt request.
+ * @param hadc ADC handle
+ * @retval None
+ */
+void HAL_ADC_IRQHandler(ADC_HandleTypeDef *hadc)
+{
+ uint32_t overrun_error = 0UL; /* flag set if overrun occurrence has to be considered as an error */
+ uint32_t tmp_isr = hadc->Instance->ISR;
+ uint32_t tmp_ier = hadc->Instance->IER;
+ uint32_t tmp_adc_inj_is_trigger_source_sw_start;
+ uint32_t tmp_adc_reg_is_trigger_source_sw_start;
+ uint32_t tmp_cfgr;
+ const ADC_TypeDef *tmpADC_Master;
+ uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_EOC_SELECTION(hadc->Init.EOCSelection));
+
+ /* ========== Check End of Sampling flag for ADC group regular ========== */
+ if (((tmp_isr & ADC_FLAG_EOSMP) == ADC_FLAG_EOSMP) && ((tmp_ier & ADC_IT_EOSMP) == ADC_IT_EOSMP))
+ {
+ /* Update state machine on end of sampling status if not in error state */
+ if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) == 0UL)
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOSMP);
+ }
+
+ /* End Of Sampling callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->EndOfSamplingCallback(hadc);
+#else
+ HAL_ADCEx_EndOfSamplingCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Clear regular group conversion flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOSMP);
+ }
+
+ /* ====== Check ADC group regular end of unitary conversion sequence conversions ===== */
+ if ((((tmp_isr & ADC_FLAG_EOC) == ADC_FLAG_EOC) && ((tmp_ier & ADC_IT_EOC) == ADC_IT_EOC)) ||
+ (((tmp_isr & ADC_FLAG_EOS) == ADC_FLAG_EOS) && ((tmp_ier & ADC_IT_EOS) == ADC_IT_EOS)))
+ {
+ /* Update state machine on conversion status if not in error state */
+ if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) == 0UL)
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+ }
+
+ /* Determine whether any further conversion upcoming on group regular */
+ /* by external trigger, continuous mode or scan sequence on going */
+ /* to disable interruption. */
+ if (LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL)
+ {
+ /* Get relevant register CFGR in ADC instance of ADC master or slave */
+ /* in function of multimode state (for devices with multimode */
+ /* available). */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_INJ_ALTERN)
+ )
+ {
+ /* check CONT bit directly in handle ADC CFGR register */
+ tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ /* else need to check Master ADC CONT bit */
+ tmpADC_Master = __LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance);
+ tmp_cfgr = READ_REG(tmpADC_Master->CFGR);
+ }
+
+ /* Carry on if continuous mode is disabled */
+ if (READ_BIT(tmp_cfgr, ADC_CFGR_CONT) != ADC_CFGR_CONT)
+ {
+ /* If End of Sequence is reached, disable interrupts */
+ if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS))
+ {
+ /* Allowed to modify bits ADC_IT_EOC/ADC_IT_EOS only if bit */
+ /* ADSTART==0 (no conversion on going) */
+ if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* Disable ADC end of sequence conversion interrupt */
+ /* Note: Overrun interrupt was enabled with EOC interrupt in */
+ /* HAL_Start_IT(), but is not disabled here because can be used */
+ /* by overrun IRQ process below. */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC | ADC_IT_EOS);
+
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+ else
+ {
+ /* Change ADC state to error state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+ }
+ }
+ }
+ }
+
+ /* Conversion complete callback */
+ /* Note: Into callback function "HAL_ADC_ConvCpltCallback()", */
+ /* to determine if conversion has been triggered from EOC or EOS, */
+ /* possibility to use: */
+ /* " if( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_EOS)) " */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->ConvCpltCallback(hadc);
+#else
+ HAL_ADC_ConvCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Clear regular group conversion flag */
+ /* Note: in case of overrun set to ADC_OVR_DATA_PRESERVED, end of */
+ /* conversion flags clear induces the release of the preserved data.*/
+ /* Therefore, if the preserved data value is needed, it must be */
+ /* read preliminarily into HAL_ADC_ConvCpltCallback(). */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS));
+ }
+
+ /* ====== Check ADC group injected end of unitary conversion sequence conversions ===== */
+ if ((((tmp_isr & ADC_FLAG_JEOC) == ADC_FLAG_JEOC) && ((tmp_ier & ADC_IT_JEOC) == ADC_IT_JEOC)) ||
+ (((tmp_isr & ADC_FLAG_JEOS) == ADC_FLAG_JEOS) && ((tmp_ier & ADC_IT_JEOS) == ADC_IT_JEOS)))
+ {
+ /* Update state machine on conversion status if not in error state */
+ if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) == 0UL)
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC);
+ }
+
+ /* Retrieve ADC configuration */
+ tmp_adc_inj_is_trigger_source_sw_start = LL_ADC_INJ_IsTriggerSourceSWStart(hadc->Instance);
+ tmp_adc_reg_is_trigger_source_sw_start = LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance);
+ /* Get relevant register CFGR in ADC instance of ADC master or slave */
+ /* in function of multimode state (for devices with multimode */
+ /* available). */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_REG_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_REG_INTERL)
+ )
+ {
+ tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ tmpADC_Master = __LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance);
+ tmp_cfgr = READ_REG(tmpADC_Master->CFGR);
+ }
+
+ /* Disable interruption if no further conversion upcoming by injected */
+ /* external trigger or by automatic injected conversion with regular */
+ /* group having no further conversion upcoming (same conditions as */
+ /* regular group interruption disabling above), */
+ /* and if injected scan sequence is completed. */
+ if ((tmp_adc_inj_is_trigger_source_sw_start != 0UL) ||
+ ((READ_BIT(tmp_cfgr, ADC_CFGR_JAUTO) == 0UL) &&
+ ((tmp_adc_reg_is_trigger_source_sw_start != 0UL) &&
+ (READ_BIT(tmp_cfgr, ADC_CFGR_CONT) == 0UL))))
+ {
+ /* If End of Sequence is reached, disable interrupts */
+ if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOS))
+ {
+ /* Particular case if injected contexts queue is enabled: */
+ /* when the last context has been fully processed, JSQR is reset */
+ /* by the hardware. Even if no injected conversion is planned to come */
+ /* (queue empty, triggers are ignored), it can start again */
+ /* immediately after setting a new context (JADSTART is still set). */
+ /* Therefore, state of HAL ADC injected group is kept to busy. */
+ if (READ_BIT(tmp_cfgr, ADC_CFGR_JQM) == 0UL)
+ {
+ /* Allowed to modify bits ADC_IT_JEOC/ADC_IT_JEOS only if bit */
+ /* JADSTART==0 (no conversion on going) */
+ if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* Disable ADC end of sequence conversion interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC | ADC_IT_JEOS);
+
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+
+ if ((hadc->State & HAL_ADC_STATE_REG_BUSY) == 0UL)
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+ }
+ }
+ }
+ }
+
+ /* Injected Conversion complete callback */
+ /* Note: HAL_ADCEx_InjectedConvCpltCallback can resort to
+ if( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_JEOS)) or
+ if( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_JEOC)) to determine whether
+ interruption has been triggered by end of conversion or end of
+ sequence. */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->InjectedConvCpltCallback(hadc);
+#else
+ HAL_ADCEx_InjectedConvCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Clear injected group conversion flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC | ADC_FLAG_JEOS);
+ }
+
+ /* ========== Check Analog watchdog 1 flag ========== */
+ if (((tmp_isr & ADC_FLAG_AWD1) == ADC_FLAG_AWD1) && ((tmp_ier & ADC_IT_AWD1) == ADC_IT_AWD1))
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+
+ /* Level out of window 1 callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->LevelOutOfWindowCallback(hadc);
+#else
+ HAL_ADC_LevelOutOfWindowCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Clear ADC analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD1);
+ }
+
+ /* ========== Check analog watchdog 2 flag ========== */
+ if (((tmp_isr & ADC_FLAG_AWD2) == ADC_FLAG_AWD2) && ((tmp_ier & ADC_IT_AWD2) == ADC_IT_AWD2))
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD2);
+
+ /* Level out of window 2 callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->LevelOutOfWindow2Callback(hadc);
+#else
+ HAL_ADCEx_LevelOutOfWindow2Callback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Clear ADC analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD2);
+ }
+
+ /* ========== Check analog watchdog 3 flag ========== */
+ if (((tmp_isr & ADC_FLAG_AWD3) == ADC_FLAG_AWD3) && ((tmp_ier & ADC_IT_AWD3) == ADC_IT_AWD3))
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD3);
+
+ /* Level out of window 3 callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->LevelOutOfWindow3Callback(hadc);
+#else
+ HAL_ADCEx_LevelOutOfWindow3Callback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Clear ADC analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD3);
+ }
+
+ /* ========== Check Overrun flag ========== */
+ if (((tmp_isr & ADC_FLAG_OVR) == ADC_FLAG_OVR) && ((tmp_ier & ADC_IT_OVR) == ADC_IT_OVR))
+ {
+ /* If overrun is set to overwrite previous data (default setting), */
+ /* overrun event is not considered as an error. */
+ /* (cf ref manual "Managing conversions without using the DMA and without */
+ /* overrun ") */
+ /* Exception for usage with DMA overrun event always considered as an */
+ /* error. */
+ if (hadc->Init.Overrun == ADC_OVR_DATA_PRESERVED)
+ {
+ overrun_error = 1UL;
+ }
+ else
+ {
+ /* Check DMA configuration */
+ if (tmp_multimode_config != LL_ADC_MULTI_INDEPENDENT)
+ {
+ /* Multimode (when feature is available) is enabled,
+ Common Control Register MDMA bits must be checked. */
+ if (LL_ADC_GetMultiDMATransfer(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) != LL_ADC_MULTI_REG_DMA_EACH_ADC)
+ {
+ overrun_error = 1UL;
+ }
+ }
+ else
+ {
+ /* Multimode not set or feature not available or ADC independent */
+ if ((hadc->Instance->CFGR & ADC_CFGR_DMNGT) != 0UL)
+ {
+ overrun_error = 1UL;
+ }
+ }
+ }
+
+ if (overrun_error == 1UL)
+ {
+ /* Change ADC state to error state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_OVR);
+
+ /* Set ADC error code to overrun */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_OVR);
+
+ /* Error callback */
+ /* Note: In case of overrun, ADC conversion data is preserved until */
+ /* flag OVR is reset. */
+ /* Therefore, old ADC conversion data can be retrieved in */
+ /* function "HAL_ADC_ErrorCallback()". */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->ErrorCallback(hadc);
+#else
+ HAL_ADC_ErrorCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+ }
+
+ /* Clear ADC overrun flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
+ }
+
+ /* ========== Check Injected context queue overflow flag ========== */
+ if (((tmp_isr & ADC_FLAG_JQOVF) == ADC_FLAG_JQOVF) && ((tmp_ier & ADC_IT_JQOVF) == ADC_IT_JQOVF))
+ {
+ /* Change ADC state to overrun state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_JQOVF);
+
+ /* Set ADC error code to Injected context queue overflow */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_JQOVF);
+
+ /* Clear the Injected context queue overflow flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JQOVF);
+
+ /* Injected context queue overflow callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->InjectedQueueOverflowCallback(hadc);
+#else
+ HAL_ADCEx_InjectedQueueOverflowCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+ }
+
+}
+
+/**
+ * @brief Conversion complete callback in non-blocking mode.
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADC_ConvCpltCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Conversion DMA half-transfer callback in non-blocking mode.
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADC_ConvHalfCpltCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Analog watchdog 1 callback in non-blocking mode.
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADC_LevelOutOfWindowCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief ADC error callback in non-blocking mode
+ * (ADC conversion with interruption or transfer by DMA).
+ * @note In case of error due to overrun when using ADC with DMA transfer
+ * (HAL ADC handle parameter "ErrorCode" to state "HAL_ADC_ERROR_OVR"):
+ * - Reinitialize the DMA using function "HAL_ADC_Stop_DMA()".
+ * - If needed, restart a new ADC conversion using function
+ * "HAL_ADC_Start_DMA()"
+ * (this function is also clearing overrun flag)
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADC_ErrorCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure channels on regular group
+ (+) Configure the analog watchdog
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure a channel to be assigned to ADC group regular.
+ * @note In case of usage of internal measurement channels:
+ * Vbat/VrefInt/TempSensor.
+ * These internal paths can be disabled using function
+ * HAL_ADC_DeInit().
+ * @note Possibility to update parameters on the fly:
+ * This function initializes channel into ADC group regular,
+ * following calls to this function can be used to reconfigure
+ * some parameters of structure "ADC_ChannelConfTypeDef" on the fly,
+ * without resetting the ADC.
+ * The setting of these parameters is conditioned to ADC state:
+ * Refer to comments of structure "ADC_ChannelConfTypeDef".
+ * @param hadc ADC handle
+ * @param sConfig Structure of ADC channel assigned to ADC group regular.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *hadc, ADC_ChannelConfTypeDef *sConfig)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ uint32_t tmpOffsetShifted;
+ uint32_t tmp_config_internal_channel;
+ __IO uint32_t wait_loop_index = 0;
+ uint32_t tmp_adc_is_conversion_on_going_regular;
+ uint32_t tmp_adc_is_conversion_on_going_injected;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_REGULAR_RANK(sConfig->Rank));
+ assert_param(IS_ADC_SAMPLE_TIME(sConfig->SamplingTime));
+ assert_param(IS_ADC_SINGLE_DIFFERENTIAL(sConfig->SingleDiff));
+ assert_param(IS_ADC_OFFSET_NUMBER(sConfig->OffsetNumber));
+ /* Check offset range according to oversampling setting */
+ if (hadc->Init.OversamplingMode == ENABLE)
+ {
+ assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), sConfig->Offset/(hadc->Init.Oversampling.Ratio+1U)));
+ }
+ else
+ {
+ assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), sConfig->Offset));
+ }
+
+ /* if ROVSE is set, the value of the OFFSETy_EN bit in ADCx_OFRy register is
+ ignored (considered as reset) */
+ assert_param(!((sConfig->OffsetNumber != ADC_OFFSET_NONE) && (hadc->Init.OversamplingMode == ENABLE)));
+
+ /* Verification of channel number */
+ if (sConfig->SingleDiff != ADC_DIFFERENTIAL_ENDED)
+ {
+ assert_param(IS_ADC_CHANNEL(sConfig->Channel));
+ }
+ else
+ {
+ if (hadc->Instance == ADC1)
+ {
+ assert_param(IS_ADC1_DIFF_CHANNEL(sConfig->Channel));
+ }
+ if (hadc->Instance == ADC2)
+ {
+ assert_param(IS_ADC2_DIFF_CHANNEL(sConfig->Channel));
+ }
+#if defined(ADC3)
+ /* ADC3 is not available on some STM32H7 products */
+ if (hadc->Instance == ADC3)
+ {
+ assert_param(IS_ADC3_DIFF_CHANNEL(sConfig->Channel));
+ }
+#endif
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated when ADC is disabled or enabled without */
+ /* conversion on going on regular group: */
+ /* - Channel number */
+ /* - Channel rank */
+ if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* ADC channels preselection */
+ hadc->Instance->PCSEL |= (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB((uint32_t)sConfig->Channel) & 0x1FUL));
+
+ /* Set ADC group regular sequence: channel on the selected scan sequence rank */
+ LL_ADC_REG_SetSequencerRanks(hadc->Instance, sConfig->Rank, sConfig->Channel);
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated when ADC is disabled or enabled without */
+ /* conversion on going on regular group: */
+ /* - Channel sampling time */
+ /* - Channel offset */
+ tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+ tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+ if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+ && (tmp_adc_is_conversion_on_going_injected == 0UL)
+ )
+ {
+ /* Set sampling time of the selected ADC channel */
+ LL_ADC_SetChannelSamplingTime(hadc->Instance, sConfig->Channel, sConfig->SamplingTime);
+
+ /* Configure the offset: offset enable/disable, channel, offset value */
+
+ /* Shift the offset with respect to the selected ADC resolution. */
+ /* Offset has to be left-aligned on bit 11, the LSB (right bits) are set to 0 */
+ tmpOffsetShifted = ADC_OFFSET_SHIFT_RESOLUTION(hadc, (uint32_t)sConfig->Offset);
+
+ if (sConfig->OffsetNumber != ADC_OFFSET_NONE)
+ {
+ /* Set ADC selected offset number */
+ LL_ADC_SetOffset(hadc->Instance, sConfig->OffsetNumber, sConfig->Channel, tmpOffsetShifted);
+
+ assert_param(IS_FUNCTIONAL_STATE(sConfig->OffsetSignedSaturation));
+ /* Set ADC selected offset signed saturation */
+ LL_ADC_SetOffsetSignedSaturation(hadc->Instance, sConfig->OffsetNumber, (sConfig->OffsetSignedSaturation == ENABLE) ? LL_ADC_OFFSET_SIGNED_SATURATION_ENABLE : LL_ADC_OFFSET_SIGNED_SATURATION_DISABLE);
+
+ assert_param(IS_FUNCTIONAL_STATE(sConfig->OffsetRightShift));
+ /* Set ADC selected offset right shift */
+ LL_ADC_SetDataRightShift(hadc->Instance, sConfig->OffsetNumber, (sConfig->OffsetRightShift == ENABLE) ? LL_ADC_OFFSET_RSHIFT_ENABLE : LL_ADC_OFFSET_RSHIFT_DISABLE);
+
+ }
+ else
+ {
+ /* Scan OFR1, OFR2, OFR3, OFR4 to check if the selected channel is enabled.
+ If this is the case, offset OFRx is disabled since
+ sConfig->OffsetNumber = ADC_OFFSET_NONE. */
+ if (((hadc->Instance->OFR1) & ADC_OFR1_OFFSET1_CH) == ADC_OFR_CHANNEL(sConfig->Channel))
+ {
+ CLEAR_BIT(hadc->Instance->OFR1, ADC_OFR1_SSATE);
+ }
+ if (((hadc->Instance->OFR2) & ADC_OFR2_OFFSET2_CH) == ADC_OFR_CHANNEL(sConfig->Channel))
+ {
+ CLEAR_BIT(hadc->Instance->OFR2, ADC_OFR2_SSATE);
+ }
+ if (((hadc->Instance->OFR3) & ADC_OFR3_OFFSET3_CH) == ADC_OFR_CHANNEL(sConfig->Channel))
+ {
+ CLEAR_BIT(hadc->Instance->OFR3, ADC_OFR3_SSATE);
+ }
+ if (((hadc->Instance->OFR4) & ADC_OFR4_OFFSET4_CH) == ADC_OFR_CHANNEL(sConfig->Channel))
+ {
+ CLEAR_BIT(hadc->Instance->OFR4, ADC_OFR4_SSATE);
+ }
+ }
+ }
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated only when ADC is disabled: */
+ /* - Single or differential mode */
+ /* - Internal measurement channels: Vbat/VrefInt/TempSensor */
+ if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+ {
+ /* Set mode single-ended or differential input of the selected ADC channel */
+ LL_ADC_SetChannelSingleDiff(hadc->Instance, sConfig->Channel, sConfig->SingleDiff);
+
+ /* Configuration of differential mode */
+ if (sConfig->SingleDiff == ADC_DIFFERENTIAL_ENDED)
+ {
+ /* Set sampling time of the selected ADC channel */
+ /* Note: ADC channel number masked with value "0x1F" to ensure shift value within 32 bits range */
+ LL_ADC_SetChannelSamplingTime(hadc->Instance,
+ (uint32_t)(__LL_ADC_DECIMAL_NB_TO_CHANNEL((__LL_ADC_CHANNEL_TO_DECIMAL_NB((uint32_t)sConfig->Channel) + 1UL) & 0x1FUL)),
+ sConfig->SamplingTime);
+ }
+
+ /* Management of internal measurement channels: Vbat/VrefInt/TempSensor. */
+ /* If internal channel selected, enable dedicated internal buffers and */
+ /* paths. */
+ /* Note: these internal measurement paths can be disabled using */
+ /* HAL_ADC_DeInit(). */
+
+ if(__LL_ADC_IS_CHANNEL_INTERNAL(sConfig->Channel))
+ {
+ /* Configuration of common ADC parameters */
+
+ tmp_config_internal_channel = LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* Software is allowed to change common parameters only when all ADCs */
+ /* of the common group are disabled. */
+ if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+ {
+ /* If the requested internal measurement path has already been enabled, */
+ /* bypass the configuration processing. */
+ if ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_TEMPSENSOR) == 0UL))
+ {
+ if (ADC_TEMPERATURE_SENSOR_INSTANCE(hadc))
+ {
+ LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_TEMPSENSOR | tmp_config_internal_channel);
+
+ /* Delay for temperature sensor stabilization time */
+ /* Wait loop initialization and execution */
+ /* Note: Variable divided by 2 to compensate partially */
+ /* CPU processing cycles, scaling in us split to not */
+ /* exceed 32 bits register capacity and handle low frequency. */
+ wait_loop_index = ((LL_ADC_DELAY_TEMPSENSOR_STAB_US / 10UL) * (SystemCoreClock / (100000UL * 2UL)));
+ while(wait_loop_index != 0UL)
+ {
+ wait_loop_index--;
+ }
+ }
+ }
+ else if ((sConfig->Channel == ADC_CHANNEL_VBAT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VBAT) == 0UL))
+ {
+ if (ADC_BATTERY_VOLTAGE_INSTANCE(hadc))
+ {
+ LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VBAT | tmp_config_internal_channel);
+ }
+ }
+ else if ((sConfig->Channel == ADC_CHANNEL_VREFINT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VREFINT) == 0UL))
+ {
+ if (ADC_VREFINT_INSTANCE(hadc))
+ {
+ LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VREFINT | tmp_config_internal_channel);
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ }
+ /* If the requested internal measurement path has already been */
+ /* enabled and other ADC of the common group are enabled, internal */
+ /* measurement paths cannot be enabled. */
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+ }
+ }
+ }
+
+ /* If a conversion is on going on regular group, no update on regular */
+ /* channel could be done on neither of the channel configuration structure */
+ /* parameters. */
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Configure the analog watchdog.
+ * @note Possibility to update parameters on the fly:
+ * This function initializes the selected analog watchdog, successive
+ * calls to this function can be used to reconfigure some parameters
+ * of structure "ADC_AnalogWDGConfTypeDef" on the fly, without resetting
+ * the ADC.
+ * The setting of these parameters is conditioned to ADC state.
+ * For parameters constraints, see comments of structure
+ * "ADC_AnalogWDGConfTypeDef".
+ * @note On this STM32 serie, analog watchdog thresholds cannot be modified
+ * while ADC conversion is on going.
+ * @param hadc ADC handle
+ * @param AnalogWDGConfig Structure of ADC analog watchdog configuration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef *hadc, ADC_AnalogWDGConfTypeDef *AnalogWDGConfig)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ uint32_t tmpAWDHighThresholdShifted;
+ uint32_t tmpAWDLowThresholdShifted;
+ uint32_t tmp_adc_is_conversion_on_going_regular;
+ uint32_t tmp_adc_is_conversion_on_going_injected;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_ANALOG_WATCHDOG_NUMBER(AnalogWDGConfig->WatchdogNumber));
+ assert_param(IS_ADC_ANALOG_WATCHDOG_MODE(AnalogWDGConfig->WatchdogMode));
+ assert_param(IS_FUNCTIONAL_STATE(AnalogWDGConfig->ITMode));
+
+ if ((AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_REG) ||
+ (AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_INJEC) ||
+ (AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_REGINJEC))
+ {
+ assert_param(IS_ADC_CHANNEL(AnalogWDGConfig->Channel));
+ }
+
+ /* Verify thresholds range */
+ if (hadc->Init.OversamplingMode == ENABLE)
+ {
+ /* Case of oversampling enabled: thresholds are compared to oversampling
+ intermediate computation (after ratio, before shift application) */
+ assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), AnalogWDGConfig->HighThreshold / (hadc->Init.Oversampling.Ratio + 1UL)));
+ assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), AnalogWDGConfig->LowThreshold / (hadc->Init.Oversampling.Ratio + 1UL)));
+ }
+ else
+ {
+ /* Verify if thresholds are within the selected ADC resolution */
+ assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), AnalogWDGConfig->HighThreshold));
+ assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), AnalogWDGConfig->LowThreshold));
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated when ADC is disabled or enabled without */
+ /* conversion on going on ADC groups regular and injected: */
+ /* - Analog watchdog channels */
+ /* - Analog watchdog thresholds */
+ tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+ tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+ if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+ && (tmp_adc_is_conversion_on_going_injected == 0UL)
+ )
+ {
+ /* Analog watchdog configuration */
+ if (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_1)
+ {
+ /* Configuration of analog watchdog: */
+ /* - Set the analog watchdog enable mode: one or overall group of */
+ /* channels, on groups regular and-or injected. */
+ switch (AnalogWDGConfig->WatchdogMode)
+ {
+ case ADC_ANALOGWATCHDOG_SINGLE_REG:
+ LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, __LL_ADC_ANALOGWD_CHANNEL_GROUP(AnalogWDGConfig->Channel,
+ LL_ADC_GROUP_REGULAR));
+ break;
+
+ case ADC_ANALOGWATCHDOG_SINGLE_INJEC:
+ LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, __LL_ADC_ANALOGWD_CHANNEL_GROUP(AnalogWDGConfig->Channel,
+ LL_ADC_GROUP_INJECTED));
+ break;
+
+ case ADC_ANALOGWATCHDOG_SINGLE_REGINJEC:
+ LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, __LL_ADC_ANALOGWD_CHANNEL_GROUP(AnalogWDGConfig->Channel,
+ LL_ADC_GROUP_REGULAR_INJECTED));
+ break;
+
+ case ADC_ANALOGWATCHDOG_ALL_REG:
+ LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, LL_ADC_AWD_ALL_CHANNELS_REG);
+ break;
+
+ case ADC_ANALOGWATCHDOG_ALL_INJEC:
+ LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, LL_ADC_AWD_ALL_CHANNELS_INJ);
+ break;
+
+ case ADC_ANALOGWATCHDOG_ALL_REGINJEC:
+ LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, LL_ADC_AWD_ALL_CHANNELS_REG_INJ);
+ break;
+
+ default: /* ADC_ANALOGWATCHDOG_NONE */
+ LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, LL_ADC_AWD_DISABLE);
+ break;
+ }
+
+ /* Shift the offset in function of the selected ADC resolution: */
+ /* Thresholds have to be left-aligned on bit 11, the LSB (right bits) */
+ /* are set to 0 */
+ tmpAWDHighThresholdShifted = ADC_AWD1THRESHOLD_SHIFT_RESOLUTION(hadc, AnalogWDGConfig->HighThreshold);
+ tmpAWDLowThresholdShifted = ADC_AWD1THRESHOLD_SHIFT_RESOLUTION(hadc, AnalogWDGConfig->LowThreshold);
+
+ /* Set the high and low thresholds */
+ MODIFY_REG(hadc->Instance->LTR1, ADC_LTR_LT , tmpAWDLowThresholdShifted);
+ MODIFY_REG(hadc->Instance->HTR1, ADC_HTR_HT , tmpAWDHighThresholdShifted);
+
+ /* Update state, clear previous result related to AWD1 */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+
+ /* Clear flag ADC analog watchdog */
+ /* Note: Flag cleared Clear the ADC Analog watchdog flag to be ready */
+ /* to use for HAL_ADC_IRQHandler() or HAL_ADC_PollForEvent() */
+ /* (in case left enabled by previous ADC operations). */
+ LL_ADC_ClearFlag_AWD1(hadc->Instance);
+
+ /* Configure ADC analog watchdog interrupt */
+ if (AnalogWDGConfig->ITMode == ENABLE)
+ {
+ LL_ADC_EnableIT_AWD1(hadc->Instance);
+ }
+ else
+ {
+ LL_ADC_DisableIT_AWD1(hadc->Instance);
+ }
+ }
+ /* Case of ADC_ANALOGWATCHDOG_2 or ADC_ANALOGWATCHDOG_3 */
+ else
+ {
+ switch (AnalogWDGConfig->WatchdogMode)
+ {
+ case ADC_ANALOGWATCHDOG_SINGLE_REG:
+ case ADC_ANALOGWATCHDOG_SINGLE_INJEC:
+ case ADC_ANALOGWATCHDOG_SINGLE_REGINJEC:
+ /* Update AWD by bitfield to keep the possibility to monitor */
+ /* several channels by successive calls of this function. */
+ if (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_2)
+ {
+ SET_BIT(hadc->Instance->AWD2CR, (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB(AnalogWDGConfig->Channel) & 0x1FUL)));
+ }
+ else
+ {
+ SET_BIT(hadc->Instance->AWD3CR, (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB(AnalogWDGConfig->Channel) & 0x1FUL)));
+ }
+ break;
+
+ case ADC_ANALOGWATCHDOG_ALL_REG:
+ case ADC_ANALOGWATCHDOG_ALL_INJEC:
+ case ADC_ANALOGWATCHDOG_ALL_REGINJEC:
+ /* Update AWD by bitfield to keep the possibility to monitor */
+ /* several channels by successive calls of this function. */
+ if (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_2)
+ {
+ SET_BIT(hadc->Instance->AWD2CR, (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB(AnalogWDGConfig->Channel) & 0x1FUL)));
+ }
+ else
+ {
+ SET_BIT(hadc->Instance->AWD3CR, (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB(AnalogWDGConfig->Channel) & 0x1FUL)));
+ }
+ break;
+
+ default: /* ADC_ANALOGWATCHDOG_NONE */
+ LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, AnalogWDGConfig->WatchdogNumber, LL_ADC_AWD_DISABLE);
+ break;
+ }
+
+ /* Shift the thresholds in function of the selected ADC resolution */
+ /* have to be left-aligned on bit 15, the LSB (right bits) are set to 0 */
+ tmpAWDHighThresholdShifted = ADC_AWD23THRESHOLD_SHIFT_RESOLUTION(hadc, AnalogWDGConfig->HighThreshold);
+ tmpAWDLowThresholdShifted = ADC_AWD23THRESHOLD_SHIFT_RESOLUTION(hadc, AnalogWDGConfig->LowThreshold);
+
+ if (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_2)
+ {
+ /* Set ADC analog watchdog thresholds value of both thresholds high and low */
+ MODIFY_REG(hadc->Instance->LTR2, ADC_LTR_LT , tmpAWDLowThresholdShifted);
+ MODIFY_REG(hadc->Instance->HTR2, ADC_HTR_HT , tmpAWDHighThresholdShifted);
+ }
+ else
+ {
+ /* Set ADC analog watchdog thresholds value of both thresholds high and low */
+ MODIFY_REG(hadc->Instance->LTR3, ADC_LTR_LT , tmpAWDLowThresholdShifted);
+ MODIFY_REG(hadc->Instance->HTR3, ADC_HTR_HT , tmpAWDHighThresholdShifted);
+ }
+
+ if (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_2)
+ {
+ /* Update state, clear previous result related to AWD2 */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_AWD2);
+
+ /* Clear flag ADC analog watchdog */
+ /* Note: Flag cleared Clear the ADC Analog watchdog flag to be ready */
+ /* to use for HAL_ADC_IRQHandler() or HAL_ADC_PollForEvent() */
+ /* (in case left enabled by previous ADC operations). */
+ LL_ADC_ClearFlag_AWD2(hadc->Instance);
+
+ /* Configure ADC analog watchdog interrupt */
+ if (AnalogWDGConfig->ITMode == ENABLE)
+ {
+ LL_ADC_EnableIT_AWD2(hadc->Instance);
+ }
+ else
+ {
+ LL_ADC_DisableIT_AWD2(hadc->Instance);
+ }
+ }
+ /* (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_3) */
+ else
+ {
+ /* Update state, clear previous result related to AWD3 */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_AWD3);
+
+ /* Clear flag ADC analog watchdog */
+ /* Note: Flag cleared Clear the ADC Analog watchdog flag to be ready */
+ /* to use for HAL_ADC_IRQHandler() or HAL_ADC_PollForEvent() */
+ /* (in case left enabled by previous ADC operations). */
+ LL_ADC_ClearFlag_AWD3(hadc->Instance);
+
+ /* Configure ADC analog watchdog interrupt */
+ if (AnalogWDGConfig->ITMode == ENABLE)
+ {
+ LL_ADC_EnableIT_AWD3(hadc->Instance);
+ }
+ else
+ {
+ LL_ADC_DisableIT_AWD3(hadc->Instance);
+ }
+ }
+ }
+
+ }
+ /* If a conversion is on going on ADC group regular or injected, no update */
+ /* could be done on neither of the AWD configuration structure parameters. */
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Exported_Functions_Group4 Peripheral State functions
+ * @brief ADC Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral state and errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions to get in run-time the status of the
+ peripheral.
+ (+) Check the ADC state
+ (+) Check the ADC error code
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the ADC handle state.
+ * @note ADC state machine is managed by bitfields, ADC status must be
+ * compared with states bits.
+ * For example:
+ * " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_REG_BUSY) != 0UL) "
+ * " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_AWD1) != 0UL) "
+ * @param hadc ADC handle
+ * @retval ADC handle state (bitfield on 32 bits)
+ */
+uint32_t HAL_ADC_GetState(ADC_HandleTypeDef *hadc)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Return ADC handle state */
+ return hadc->State;
+}
+
+/**
+ * @brief Return the ADC error code.
+ * @param hadc ADC handle
+ * @retval ADC error code (bitfield on 32 bits)
+ */
+uint32_t HAL_ADC_GetError(ADC_HandleTypeDef *hadc)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ return hadc->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Private_Functions ADC Private Functions
+ * @{
+ */
+
+/**
+ * @brief Stop ADC conversion.
+ * @param hadc ADC handle
+ * @param ConversionGroup ADC group regular and/or injected.
+ * This parameter can be one of the following values:
+ * @arg @ref ADC_REGULAR_GROUP ADC regular conversion type.
+ * @arg @ref ADC_INJECTED_GROUP ADC injected conversion type.
+ * @arg @ref ADC_REGULAR_INJECTED_GROUP ADC regular and injected conversion type.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef ADC_ConversionStop(ADC_HandleTypeDef *hadc, uint32_t ConversionGroup)
+{
+ uint32_t tickstart;
+ uint32_t Conversion_Timeout_CPU_cycles = 0UL;
+ uint32_t conversion_group_reassigned = ConversionGroup;
+ uint32_t tmp_ADC_CR_ADSTART_JADSTART;
+ uint32_t tmp_adc_is_conversion_on_going_regular;
+ uint32_t tmp_adc_is_conversion_on_going_injected;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_CONVERSION_GROUP(ConversionGroup));
+
+ /* Verification if ADC is not already stopped (on regular and injected */
+ /* groups) to bypass this function if not needed. */
+ tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+ tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+ if ((tmp_adc_is_conversion_on_going_regular != 0UL)
+ || (tmp_adc_is_conversion_on_going_injected != 0UL)
+ )
+ {
+ /* Particular case of continuous auto-injection mode combined with */
+ /* auto-delay mode. */
+ /* In auto-injection mode, regular group stop ADC_CR_ADSTP is used (not */
+ /* injected group stop ADC_CR_JADSTP). */
+ /* Procedure to be followed: Wait until JEOS=1, clear JEOS, set ADSTP=1 */
+ /* (see reference manual). */
+ if (((hadc->Instance->CFGR & ADC_CFGR_JAUTO) != 0UL)
+ && (hadc->Init.ContinuousConvMode == ENABLE)
+ && (hadc->Init.LowPowerAutoWait == ENABLE)
+ )
+ {
+ /* Use stop of regular group */
+ conversion_group_reassigned = ADC_REGULAR_GROUP;
+
+ /* Wait until JEOS=1 (maximum Timeout: 4 injected conversions) */
+ while (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOS) == 0UL)
+ {
+ if (Conversion_Timeout_CPU_cycles >= (ADC_CONVERSION_TIME_MAX_CPU_CYCLES * 4UL))
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+ Conversion_Timeout_CPU_cycles ++;
+ }
+
+ /* Clear JEOS */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOS);
+ }
+
+ /* Stop potential conversion on going on ADC group regular */
+ if (conversion_group_reassigned != ADC_INJECTED_GROUP)
+ {
+ /* Software is allowed to set ADSTP only when ADSTART=1 and ADDIS=0 */
+ if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) != 0UL)
+ {
+ if (LL_ADC_IsDisableOngoing(hadc->Instance) == 0UL)
+ {
+ /* Stop ADC group regular conversion */
+ LL_ADC_REG_StopConversion(hadc->Instance);
+ }
+ }
+ }
+
+ /* Stop potential conversion on going on ADC group injected */
+ if (conversion_group_reassigned != ADC_REGULAR_GROUP)
+ {
+ /* Software is allowed to set JADSTP only when JADSTART=1 and ADDIS=0 */
+ if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) != 0UL)
+ {
+ if (LL_ADC_IsDisableOngoing(hadc->Instance) == 0UL)
+ {
+ /* Stop ADC group injected conversion */
+ LL_ADC_INJ_StopConversion(hadc->Instance);
+ }
+ }
+ }
+
+ /* Selection of start and stop bits with respect to the regular or injected group */
+ switch (conversion_group_reassigned)
+ {
+ case ADC_REGULAR_INJECTED_GROUP:
+ tmp_ADC_CR_ADSTART_JADSTART = (ADC_CR_ADSTART | ADC_CR_JADSTART);
+ break;
+ case ADC_INJECTED_GROUP:
+ tmp_ADC_CR_ADSTART_JADSTART = ADC_CR_JADSTART;
+ break;
+ /* Case ADC_REGULAR_GROUP only*/
+ default:
+ tmp_ADC_CR_ADSTART_JADSTART = ADC_CR_ADSTART;
+ break;
+ }
+
+ /* Wait for conversion effectively stopped */
+ tickstart = HAL_GetTick();
+
+ while ((hadc->Instance->CR & tmp_ADC_CR_ADSTART_JADSTART) != 0UL)
+ {
+ if ((HAL_GetTick() - tickstart) > ADC_STOP_CONVERSION_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+ }
+
+ }
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+
+
+/**
+ * @brief Enable the selected ADC.
+ * @note Prerequisite condition to use this function: ADC must be disabled
+ * and voltage regulator must be enabled (done into HAL_ADC_Init()).
+ * @param hadc ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef ADC_Enable(ADC_HandleTypeDef *hadc)
+{
+ uint32_t tickstart;
+
+ /* ADC enable and wait for ADC ready (in case of ADC is disabled or */
+ /* enabling phase not yet completed: flag ADC ready not yet set). */
+ /* Timeout implemented to not be stuck if ADC cannot be enabled (possible */
+ /* causes: ADC clock not running, ...). */
+ if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+ {
+ /* Check if conditions to enable the ADC are fulfilled */
+ if ((hadc->Instance->CR & (ADC_CR_ADCAL | ADC_CR_JADSTP | ADC_CR_ADSTP | ADC_CR_JADSTART | ADC_CR_ADSTART | ADC_CR_ADDIS | ADC_CR_ADEN)) != 0UL)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the ADC peripheral */
+ LL_ADC_Enable(hadc->Instance);
+
+ /* Wait for ADC effectively enabled */
+ tickstart = HAL_GetTick();
+
+ /* Poll for ADC ready flag raised except case of multimode enabled
+ and ADC slave selected. */
+ uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+ if ( (__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ )
+ {
+ while(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == 0UL)
+ {
+ /* If ADEN bit is set less than 4 ADC clock cycles after the ADCAL bit
+ has been cleared (after a calibration), ADEN bit is reset by the
+ calibration logic.
+ The workaround is to continue setting ADEN until ADRDY is becomes 1.
+ Additionally, ADC_ENABLE_TIMEOUT is defined to encompass this
+ 4 ADC clock cycle duration */
+ /* Note: Test of ADC enabled required due to hardware constraint to */
+ /* not enable ADC if already enabled. */
+ if(LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+ {
+ LL_ADC_Enable(hadc->Instance);
+ }
+
+ if((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the selected ADC.
+ * @note Prerequisite condition to use this function: ADC conversions must be
+ * stopped.
+ * @param hadc ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef ADC_Disable(ADC_HandleTypeDef *hadc)
+{
+ uint32_t tickstart;
+ const uint32_t tmp_adc_is_disable_on_going = LL_ADC_IsDisableOngoing(hadc->Instance);
+
+ /* Verification if ADC is not already disabled: */
+ /* Note: forbidden to disable ADC (set bit ADC_CR_ADDIS) if ADC is already */
+ /* disabled. */
+ if ((LL_ADC_IsEnabled(hadc->Instance) != 0UL)
+ && (tmp_adc_is_disable_on_going == 0UL)
+ )
+ {
+ /* Check if conditions to disable the ADC are fulfilled */
+ if ((hadc->Instance->CR & (ADC_CR_JADSTART | ADC_CR_ADSTART | ADC_CR_ADEN)) == ADC_CR_ADEN)
+ {
+ /* Disable the ADC peripheral */
+ LL_ADC_Disable(hadc->Instance);
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOSMP | ADC_FLAG_RDY));
+ }
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+
+ /* Wait for ADC effectively disabled */
+ /* Get tick count */
+ tickstart = HAL_GetTick();
+
+ while ((hadc->Instance->CR & ADC_CR_ADEN) != 0UL)
+ {
+ if ((HAL_GetTick() - tickstart) > ADC_DISABLE_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DMA transfer complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Retrieve ADC handle corresponding to current DMA handle */
+ ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Update state machine on conversion status if not in error state */
+ if ((hadc->State & (HAL_ADC_STATE_ERROR_INTERNAL | HAL_ADC_STATE_ERROR_DMA)) == 0UL)
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+
+ /* Determine whether any further conversion upcoming on group regular */
+ /* by external trigger, continuous mode or scan sequence on going */
+ /* to disable interruption. */
+ /* Is it the end of the regular sequence ? */
+ if ((hadc->Instance->ISR & ADC_FLAG_EOS) != 0UL)
+ {
+ /* Are conversions software-triggered ? */
+ if (LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL)
+ {
+ /* Is CONT bit set ? */
+ if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_CONT) == 0UL)
+ {
+ /* CONT bit is not set, no more conversions expected */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+ if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* DMA End of Transfer interrupt was triggered but conversions sequence
+ is not over. If DMACFG is set to 0, conversions are stopped. */
+ if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_DMNGT) == 0UL)
+ {
+ /* DMACFG bit is not set, conversions are stopped. */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+ if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+ }
+
+ /* Conversion complete callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->ConvCpltCallback(hadc);
+#else
+ HAL_ADC_ConvCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+ }
+ else /* DMA and-or internal error occurred */
+ {
+ if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) != 0UL)
+ {
+ /* Call HAL ADC Error Callback function */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->ErrorCallback(hadc);
+#else
+ HAL_ADC_ErrorCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Call ADC DMA error callback */
+ hadc->DMA_Handle->XferErrorCallback(hdma);
+ }
+ }
+}
+
+/**
+ * @brief DMA half transfer complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Retrieve ADC handle corresponding to current DMA handle */
+ ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Half conversion callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->ConvHalfCpltCallback(hadc);
+#else
+ HAL_ADC_ConvHalfCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA error callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void ADC_DMAError(DMA_HandleTypeDef *hdma)
+{
+ /* Retrieve ADC handle corresponding to current DMA handle */
+ ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+
+ /* Set ADC error code to DMA error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_DMA);
+
+ /* Error callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->ErrorCallback(hadc);
+#else
+ HAL_ADC_ErrorCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief Configure boost mode of selected ADC.
+ * @note Prerequisite condition to use this function: ADC conversions must be
+ * stopped.
+ * @param hadc ADC handle
+ * @retval None.
+ */
+void ADC_ConfigureBoostMode(ADC_HandleTypeDef* hadc)
+{
+ uint32_t freq;
+ if(ADC_IS_SYNCHRONOUS_CLOCK_MODE(hadc))
+ {
+ freq = HAL_RCC_GetHCLKFreq();
+ switch(hadc->Init.ClockPrescaler)
+ {
+ case ADC_CLOCK_SYNC_PCLK_DIV1:
+ case ADC_CLOCK_SYNC_PCLK_DIV2:
+ freq /= (hadc->Init.ClockPrescaler >> ADC_CCR_CKMODE_Pos);
+ break;
+ case ADC_CLOCK_SYNC_PCLK_DIV4:
+ freq /= 4UL;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_ADC);
+ switch(hadc->Init.ClockPrescaler)
+ {
+ case ADC_CLOCK_ASYNC_DIV2:
+ case ADC_CLOCK_ASYNC_DIV4:
+ case ADC_CLOCK_ASYNC_DIV6:
+ case ADC_CLOCK_ASYNC_DIV8:
+ case ADC_CLOCK_ASYNC_DIV10:
+ case ADC_CLOCK_ASYNC_DIV12:
+ freq /= ((hadc->Init.ClockPrescaler >> ADC_CCR_PRESC_Pos) << 1UL);
+ break;
+ case ADC_CLOCK_ASYNC_DIV16:
+ freq /= 16UL;
+ break;
+ case ADC_CLOCK_ASYNC_DIV32:
+ freq /= 32UL;
+ break;
+ case ADC_CLOCK_ASYNC_DIV64:
+ freq /= 64UL;
+ break;
+ case ADC_CLOCK_ASYNC_DIV128:
+ freq /= 128UL;
+ break;
+ case ADC_CLOCK_ASYNC_DIV256:
+ freq /= 256UL;
+ break;
+ default:
+ break;
+ }
+ }
+
+#if defined(ADC_VER_V5_3)
+ freq /= 2U;
+
+ if (freq <= 6250000UL)
+ {
+ MODIFY_REG(hadc->Instance->CR, ADC_CR_BOOST, 0UL);
+ }
+ else if(freq <= 12500000UL)
+ {
+ MODIFY_REG(hadc->Instance->CR, ADC_CR_BOOST, ADC_CR_BOOST_0);
+ }
+ else if(freq <= 25000000UL)
+ {
+ MODIFY_REG(hadc->Instance->CR, ADC_CR_BOOST, ADC_CR_BOOST_1);
+ }
+ else /* if(freq > 25000000UL) */
+ {
+ MODIFY_REG(hadc->Instance->CR, ADC_CR_BOOST, ADC_CR_BOOST_1 | ADC_CR_BOOST_0);
+ }
+#else
+ if(HAL_GetREVID() <= REV_ID_Y) /* STM32H7 silicon Rev.Y */
+ {
+ if(freq > 20000000UL)
+ {
+ SET_BIT(hadc->Instance->CR, ADC_CR_BOOST_0);
+ }
+ else
+ {
+ CLEAR_BIT(hadc->Instance->CR, ADC_CR_BOOST_0);
+ }
+ }
+ else /* STM32H7 silicon Rev.V */
+ {
+ freq /= 2U; /* divider by 2 for Rev.V */
+
+ if (freq <= 6250000UL)
+ {
+ MODIFY_REG(hadc->Instance->CR, ADC_CR_BOOST, 0UL);
+ }
+ else if(freq <= 12500000UL)
+ {
+ MODIFY_REG(hadc->Instance->CR, ADC_CR_BOOST, ADC_CR_BOOST_0);
+ }
+ else if(freq <= 25000000UL)
+ {
+ MODIFY_REG(hadc->Instance->CR, ADC_CR_BOOST, ADC_CR_BOOST_1);
+ }
+ else /* if(freq > 25000000UL) */
+ {
+ MODIFY_REG(hadc->Instance->CR, ADC_CR_BOOST, ADC_CR_BOOST_1 | ADC_CR_BOOST_0);
+ }
+ }
+#endif /* ADC_VER_V5_3 */
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_adc_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_adc_ex.c
new file mode 100644
index 0000000000..8aa0815044
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_adc_ex.c
@@ -0,0 +1,2492 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_adc_ex.c
+ * @author MCD Application Team
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Analog to Digital Convertor (ADC)
+ * peripheral:
+ * + Operation functions
+ * ++ Start, stop, get result of conversions of ADC group injected,
+ * using 2 possible modes: polling, interruption.
+ * ++ Calibration
+ * +++ ADC automatic self-calibration
+ * +++ Calibration factors get or set
+ * ++ Multimode feature when available
+ * + Control functions
+ * ++ Channels configuration on ADC group injected
+ * + State functions
+ * ++ ADC group injected contexts queue management
+ * Other functions (generic functions) are available in file
+ * "stm32h7xx_hal_adc.c".
+ *
+ @verbatim
+ [..]
+ (@) Sections "ADC peripheral features" and "How to use this driver" are
+ available in file of generic functions "stm32h7xx_hal_adc.c".
+ [..]
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup ADCEx ADCEx
+ * @brief ADC Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup ADCEx_Private_Constants ADC Extended Private Constants
+ * @{
+ */
+
+#define ADC_JSQR_FIELDS ((ADC_JSQR_JL | ADC_JSQR_JEXTSEL | ADC_JSQR_JEXTEN |\
+ ADC_JSQR_JSQ1 | ADC_JSQR_JSQ2 |\
+ ADC_JSQR_JSQ3 | ADC_JSQR_JSQ4 )) /*!< ADC_JSQR fields of parameters that can be updated anytime
+ once the ADC is enabled */
+
+/* Fixed timeout value for ADC calibration. */
+/* Fixed timeout value for ADC calibration. */
+/* Values defined to be higher than worst cases: low clock frequency, */
+/* maximum prescalers. */
+/* Ex of profile low frequency : f_ADC at 0.125 Mhz (minimum value */
+/* according to Data sheet), calibration_time MAX = 165010 / f_ADC */
+/* 165010 / 125000 = 1.32s */
+/* At maximum CPU speed (480 MHz), this means */
+/* 1.32 * 480 MHz = 633600000 CPU cycles */
+#define ADC_CALIBRATION_TIMEOUT (633600000U) /*!< ADC calibration time-out value */
+
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup ADCEx_Exported_Functions ADC Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup ADCEx_Exported_Functions_Group1 Extended Input and Output operation functions
+ * @brief Extended IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+
+ (+) Perform the ADC self-calibration for single or differential ending.
+ (+) Get calibration factors for single or differential ending.
+ (+) Set calibration factors for single or differential ending.
+
+ (+) Start conversion of ADC group injected.
+ (+) Stop conversion of ADC group injected.
+ (+) Poll for conversion complete on ADC group injected.
+ (+) Get result of ADC group injected channel conversion.
+ (+) Start conversion of ADC group injected and enable interruptions.
+ (+) Stop conversion of ADC group injected and disable interruptions.
+
+ (+) When multimode feature is available, start multimode and enable DMA transfer.
+ (+) Stop multimode and disable ADC DMA transfer.
+ (+) Get result of multimode conversion.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Perform an ADC automatic self-calibration
+ * Calibration prerequisite: ADC must be disabled (execute this
+ * function before HAL_ADC_Start() or after HAL_ADC_Stop() ).
+ * @param hadc ADC handle
+* @param CalibrationMode Selection of calibration offset or
+ * linear calibration offset.
+ * @arg ADC_CALIB_OFFSET Channel in mode calibration offset
+ * @arg ADC_CALIB_OFFSET_LINEARITY Channel in mode linear calibration offset
+ * @param SingleDiff Selection of single-ended or differential input
+ * This parameter can be one of the following values:
+ * @arg @ref ADC_SINGLE_ENDED Channel in mode input single ended
+ * @arg @ref ADC_DIFFERENTIAL_ENDED Channel in mode input differential ended
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *hadc, uint32_t CalibrationMode, uint32_t SingleDiff)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ __IO uint32_t wait_loop_index = 0UL;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Calibration prerequisite: ADC must be disabled. */
+
+ /* Disable the ADC (if not already disabled) */
+ tmp_hal_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_BUSY_INTERNAL);
+
+ /* Start ADC calibration in mode single-ended or differential */
+ LL_ADC_StartCalibration(hadc->Instance , CalibrationMode, SingleDiff );
+
+ /* Wait for calibration completion */
+ while (LL_ADC_IsCalibrationOnGoing(hadc->Instance) != 0UL)
+ {
+ wait_loop_index++;
+ if (wait_loop_index >= ADC_CALIBRATION_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_BUSY_INTERNAL,
+ HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_BUSY_INTERNAL,
+ HAL_ADC_STATE_READY);
+ }
+ else
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Note: No need to update variable "tmp_hal_status" here: already set */
+ /* to state "HAL_ERROR" by function disabling the ADC. */
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Get the calibration factor.
+ * @param hadc ADC handle.
+ * @param SingleDiff This parameter can be only:
+ * @arg @ref ADC_SINGLE_ENDED Channel in mode input single ended
+ * @arg @ref ADC_DIFFERENTIAL_ENDED Channel in mode input differential ended
+ * @retval Calibration value.
+ */
+uint32_t HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef *hadc, uint32_t SingleDiff)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
+
+ /* Return the selected ADC calibration value */
+ return LL_ADC_GetCalibrationOffsetFactor(hadc->Instance, SingleDiff);
+}
+
+/**
+ * @brief Get the calibration factor from automatic conversion result
+ * @param hadc ADC handle
+ * @param LinearCalib_Buffer: Linear calibration factor
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_ADCEx_LinearCalibration_GetValue(ADC_HandleTypeDef* hadc, uint32_t* LinearCalib_Buffer)
+{
+ uint32_t cnt;
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ uint32_t temp_REG_IsConversionOngoing = 0UL;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Enable the ADC ADEN = 1 to be able to read the linear calibration factor */
+ if(LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+ {
+ tmp_hal_status = ADC_Enable(hadc);
+ }
+
+ if (tmp_hal_status == HAL_OK)
+ {
+ if(LL_ADC_REG_IsConversionOngoing(hadc->Instance) != 0UL)
+ {
+ LL_ADC_REG_StopConversion(hadc->Instance);
+ temp_REG_IsConversionOngoing = 1UL;
+ }
+ for(cnt = ADC_LINEAR_CALIB_REG_COUNT; cnt > 0UL; cnt--)
+ {
+ LinearCalib_Buffer[cnt-1U]=LL_ADC_GetCalibrationLinearFactor(hadc->Instance, ADC_CR_LINCALRDYW6 >> (ADC_LINEAR_CALIB_REG_COUNT-cnt));
+ }
+ if(temp_REG_IsConversionOngoing != 0UL)
+ {
+ LL_ADC_REG_StartConversion(hadc->Instance);
+ }
+ }
+
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Set the calibration factor to overwrite automatic conversion result.
+ * ADC must be enabled and no conversion is ongoing.
+ * @param hadc ADC handle
+ * @param SingleDiff This parameter can be only:
+ * @arg @ref ADC_SINGLE_ENDED Channel in mode input single ended
+ * @arg @ref ADC_DIFFERENTIAL_ENDED Channel in mode input differential ended
+ * @param CalibrationFactor Calibration factor (coded on 7 bits maximum)
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef *hadc, uint32_t SingleDiff, uint32_t CalibrationFactor)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ uint32_t tmp_adc_is_conversion_on_going_regular;
+ uint32_t tmp_adc_is_conversion_on_going_injected;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
+ assert_param(IS_ADC_CALFACT(CalibrationFactor));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Verification of hardware constraints before modifying the calibration */
+ /* factors register: ADC must be enabled, no conversion on going. */
+ tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+ tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+
+ if ((LL_ADC_IsEnabled(hadc->Instance) != 0UL)
+ && (tmp_adc_is_conversion_on_going_regular == 0UL)
+ && (tmp_adc_is_conversion_on_going_injected == 0UL)
+ )
+ {
+ /* Set the selected ADC calibration value */
+ LL_ADC_SetCalibrationOffsetFactor(hadc->Instance, SingleDiff, CalibrationFactor);
+ }
+ else
+ {
+ /* Update ADC state machine */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+ /* Update ADC error code */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ /* Update ADC state machine to error */
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Set the linear calibration factor
+ * @param hadc ADC handle
+ * @param LinearCalib_Buffer: Linear calibration factor
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_ADCEx_LinearCalibration_SetValue(ADC_HandleTypeDef *hadc, uint32_t* LinearCalib_Buffer)
+{
+ uint32_t cnt;
+ __IO uint32_t wait_loop_index = 0;
+ uint32_t temp_REG_IsConversionOngoing = 0UL;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* - Exit from deep-power-down mode and ADC voltage regulator enable */
+ /* Exit deep power down mode if still in that state */
+ if (HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_DEEPPWD))
+ {
+ /* Exit deep power down mode */
+ CLEAR_BIT(hadc->Instance->CR, ADC_CR_DEEPPWD);
+
+ /* System was in deep power down mode, calibration must
+ be relaunched or a previously saved calibration factor
+ re-applied once the ADC voltage regulator is enabled */
+ }
+
+
+ if (HAL_IS_BIT_CLR(hadc->Instance->CR, ADC_CR_ADVREGEN))
+ {
+ /* Enable ADC internal voltage regulator */
+ SET_BIT(hadc->Instance->CR, ADC_CR_ADVREGEN);
+ /* Delay for ADC stabilization time */
+ /* Wait loop initialization and execution */
+ /* Note: Variable divided by 2 to compensate partially */
+ /* CPU processing cycles. */
+ wait_loop_index = (ADC_STAB_DELAY_US * (SystemCoreClock / (1000000UL * 2UL)));
+ while(wait_loop_index != 0UL)
+ {
+ wait_loop_index--;
+ }
+ }
+
+
+ /* Verification that ADC voltage regulator is correctly enabled, whether */
+ /* or not ADC is coming from state reset (if any potential problem of */
+ /* clocking, voltage regulator would not be enabled). */
+ if (HAL_IS_BIT_CLR(hadc->Instance->CR, ADC_CR_ADVREGEN))
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC peripheral internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+/* Enable the ADC peripheral */
+ if(LL_ADC_IsEnabled(hadc->Instance) == 0UL) /* Enable the ADC if it is disabled */
+ {
+ if (ADC_Enable(hadc) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ for(cnt = ADC_LINEAR_CALIB_REG_COUNT; cnt > 0UL ; cnt--)
+ {
+ LL_ADC_SetCalibrationLinearFactor(hadc->Instance, ADC_CR_LINCALRDYW6 >> (ADC_LINEAR_CALIB_REG_COUNT-cnt), LinearCalib_Buffer[cnt-1U]);
+ }
+ (void)ADC_Disable(hadc);
+ }
+ }else /* ADC is already enabled, so no need to enable it but need to stop conversion */
+ {
+ if(LL_ADC_REG_IsConversionOngoing(hadc->Instance) != 0UL)
+ {
+ LL_ADC_REG_StopConversion(hadc->Instance);
+ temp_REG_IsConversionOngoing = 1UL;
+ }
+ for(cnt = ADC_LINEAR_CALIB_REG_COUNT; cnt > 0UL ; cnt--)
+ {
+ LL_ADC_SetCalibrationLinearFactor(hadc->Instance, ADC_CR_LINCALRDYW6 >> (ADC_LINEAR_CALIB_REG_COUNT-cnt), LinearCalib_Buffer[cnt-1U]);
+ }
+ if(temp_REG_IsConversionOngoing != 0UL)
+ {
+ LL_ADC_REG_StartConversion(hadc->Instance);
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Load the calibration factor from engi bytes
+ * @param hadc ADC handle
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_ADCEx_LinearCalibration_FactorLoad(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ uint32_t cnt, FactorOffset;
+ uint32_t LinearCalib_Buffer[ADC_LINEAR_CALIB_REG_COUNT];
+
+ /* Linearity calibration is retrieved from engi bytes
+ read values from registers and put them to the CALFACT2 register */
+ /* If needed linearity calibration can be done in runtime using
+ LL_ADC_GetCalibrationLinearFactor() */
+ if(hadc->Instance == ADC1)
+ {
+ FactorOffset = 0UL;
+ }else if(hadc->Instance == ADC2)
+ {
+ FactorOffset = 8UL;
+ }else /*Case ADC3*/
+ {
+ FactorOffset = 16UL;
+ }
+
+ for (cnt = 0UL; cnt < ADC_LINEAR_CALIB_REG_COUNT; cnt++)
+ {
+ LinearCalib_Buffer[cnt] = *(uint32_t*)(ADC_LINEAR_CALIB_REG_1_ADDR + FactorOffset + cnt);
+ }
+ if (HAL_ADCEx_LinearCalibration_SetValue(hadc,(uint32_t*)LinearCalib_Buffer) != HAL_OK)
+ {
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Enable ADC, start conversion of injected group.
+ * @note Interruptions enabled in this function: None.
+ * @note Case of multimode enabled when multimode feature is available:
+ * HAL_ADCEx_InjectedStart() API must be called for ADC slave first,
+ * then for ADC master.
+ * For ADC slave, ADC is enabled only (conversion is not started).
+ * For ADC master, ADC is enabled and multimode conversion is started.
+ * @param hadc ADC handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ uint32_t tmp_config_injected_queue;
+ uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) != 0UL)
+ {
+ return HAL_BUSY;
+ }
+ else
+ {
+ /* In case of software trigger detection enabled, JQDIS must be set
+ (which can be done only if ADSTART and JADSTART are both cleared).
+ If JQDIS is not set at that point, returns an error
+ - since software trigger detection is disabled. User needs to
+ resort to HAL_ADCEx_DisableInjectedQueue() API to set JQDIS.
+ - or (if JQDIS is intentionally reset) since JEXTEN = 0 which means
+ the queue is empty */
+ tmp_config_injected_queue = READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS);
+
+ if ((READ_BIT(hadc->Instance->JSQR, ADC_JSQR_JEXTEN) == 0UL)
+ && (tmp_config_injected_queue == 0UL)
+ )
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_hal_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Check if a regular conversion is ongoing */
+ if ((hadc->State & HAL_ADC_STATE_REG_BUSY) != 0UL)
+ {
+ /* Reset ADC error code field related to injected conversions only */
+ CLEAR_BIT(hadc->ErrorCode, HAL_ADC_ERROR_JQOVF);
+ }
+ else
+ {
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Set ADC state */
+ /* - Clear state bitfield related to injected group conversion results */
+ /* - Set state bitfield related to injected operation */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_READY | HAL_ADC_STATE_INJ_EOC,
+ HAL_ADC_STATE_INJ_BUSY);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - if ADC instance is master or if multimode feature is not available
+ - if multimode setting is disabled (ADC instance slave in independent mode) */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ )
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* Clear ADC group injected group conversion flag */
+ /* (To ensure of no unknown state from potential previous ADC operations) */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_JEOC | ADC_FLAG_JEOS));
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* Enable conversion of injected group, if automatic injected conversion */
+ /* is disabled. */
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ /* Case of multimode enabled (when multimode feature is available): */
+ /* if ADC is slave, */
+ /* - ADC is enabled only (conversion is not started), */
+ /* - if multimode only concerns regular conversion, ADC is enabled */
+ /* and conversion is started. */
+ /* If ADC is master or independent, */
+ /* - ADC is enabled and conversion is started. */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_REG_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_REG_INTERL)
+ )
+ {
+ /* ADC instance is not a multimode slave instance with multimode injected conversions enabled */
+ if (LL_ADC_INJ_GetTrigAuto(hadc->Instance) == LL_ADC_INJ_TRIG_INDEPENDENT)
+ {
+ LL_ADC_INJ_StartConversion(hadc->Instance);
+ }
+ }
+ else
+ {
+ /* ADC instance is not a multimode slave instance with multimode injected conversions enabled */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ /* Return function status */
+ return tmp_hal_status;
+ }
+}
+
+/**
+ * @brief Stop conversion of injected channels. Disable ADC peripheral if
+ * no regular conversion is on going.
+ * @note If ADC must be disabled and if conversion is on going on
+ * regular group, function HAL_ADC_Stop must be used to stop both
+ * injected and regular groups, and disable the ADC.
+ * @note If injected group mode auto-injection is enabled,
+ * function HAL_ADC_Stop must be used.
+ * @note In case of multimode enabled (when multimode feature is available),
+ * HAL_ADCEx_InjectedStop() must be called for ADC master first, then for ADC slave.
+ * For ADC master, conversion is stopped and ADC is disabled.
+ * For ADC slave, ADC is disabled only (conversion stop of ADC master
+ * has already stopped conversion of ADC slave).
+ * @param hadc ADC handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential conversion on going on injected group only. */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if injected conversions are effectively stopped */
+ /* and if no conversion on regular group is on-going */
+ if (tmp_hal_status == HAL_OK)
+ {
+ if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* 2. Disable the ADC peripheral */
+ tmp_hal_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+ }
+ /* Conversion on injected group is stopped, but ADC not disabled since */
+ /* conversion on regular group is still running. */
+ else
+ {
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Wait for injected group conversion to be completed.
+ * @param hadc ADC handle
+ * @param Timeout Timeout value in millisecond.
+ * @note Depending on hadc->Init.EOCSelection, JEOS or JEOC is
+ * checked and cleared depending on AUTDLY bit status.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t tmp_Flag_End;
+ uint32_t tmp_adc_inj_is_trigger_source_sw_start;
+ uint32_t tmp_adc_reg_is_trigger_source_sw_start;
+ uint32_t tmp_cfgr;
+ const ADC_TypeDef *tmpADC_Master;
+ uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* If end of sequence selected */
+ if (hadc->Init.EOCSelection == ADC_EOC_SEQ_CONV)
+ {
+ tmp_Flag_End = ADC_FLAG_JEOS;
+ }
+ else /* end of conversion selected */
+ {
+ tmp_Flag_End = ADC_FLAG_JEOC;
+ }
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait until End of Conversion or Sequence flag is raised */
+ while ((hadc->Instance->ISR & tmp_Flag_End) == 0UL)
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+ {
+ /* Update ADC state machine to timeout */
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Retrieve ADC configuration */
+ tmp_adc_inj_is_trigger_source_sw_start = LL_ADC_INJ_IsTriggerSourceSWStart(hadc->Instance);
+ tmp_adc_reg_is_trigger_source_sw_start = LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance);
+ /* Get relevant register CFGR in ADC instance of ADC master or slave */
+ /* in function of multimode state (for devices with multimode */
+ /* available). */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_REG_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_REG_INTERL)
+ )
+ {
+ tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ tmpADC_Master = __LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance);
+ tmp_cfgr = READ_REG(tmpADC_Master->CFGR);
+ }
+
+ /* Update ADC state machine */
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC);
+
+ /* Determine whether any further conversion upcoming on group injected */
+ /* by external trigger or by automatic injected conversion */
+ /* from group regular. */
+ if ((tmp_adc_inj_is_trigger_source_sw_start != 0UL) ||
+ ((READ_BIT(tmp_cfgr, ADC_CFGR_JAUTO) == 0UL) &&
+ ((tmp_adc_reg_is_trigger_source_sw_start != 0UL) &&
+ (READ_BIT(tmp_cfgr, ADC_CFGR_CONT) == 0UL))))
+ {
+ /* Check whether end of sequence is reached */
+ if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOS))
+ {
+ /* Particular case if injected contexts queue is enabled: */
+ /* when the last context has been fully processed, JSQR is reset */
+ /* by the hardware. Even if no injected conversion is planned to come */
+ /* (queue empty, triggers are ignored), it can start again */
+ /* immediately after setting a new context (JADSTART is still set). */
+ /* Therefore, state of HAL ADC injected group is kept to busy. */
+ if (READ_BIT(tmp_cfgr, ADC_CFGR_JQM) == 0UL)
+ {
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+
+ if ((hadc->State & HAL_ADC_STATE_REG_BUSY) == 0UL)
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+ }
+ }
+
+ /* Clear polled flag */
+ if (tmp_Flag_End == ADC_FLAG_JEOS)
+ {
+ /* Clear end of sequence JEOS flag of injected group if low power feature */
+ /* "LowPowerAutoWait " is disabled, to not interfere with this feature. */
+ /* For injected groups, no new conversion will start before JEOS is */
+ /* cleared. */
+ if (READ_BIT(tmp_cfgr, ADC_CFGR_AUTDLY) == 0UL)
+ {
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_JEOC | ADC_FLAG_JEOS));
+ }
+ }
+ else
+ {
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC);
+ }
+
+ /* Return API HAL status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable ADC, start conversion of injected group with interruption.
+ * @note Interruptions enabled in this function according to initialization
+ * setting : JEOC (end of conversion) or JEOS (end of sequence)
+ * @note Case of multimode enabled (when multimode feature is enabled):
+ * HAL_ADCEx_InjectedStart_IT() API must be called for ADC slave first,
+ * then for ADC master.
+ * For ADC slave, ADC is enabled only (conversion is not started).
+ * For ADC master, ADC is enabled and multimode conversion is started.
+ * @param hadc ADC handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ uint32_t tmp_config_injected_queue;
+ uint32_t tmp_multimode_config = LL_ADC_GetMultimode(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) != 0UL)
+ {
+ return HAL_BUSY;
+ }
+ else
+ {
+ /* In case of software trigger detection enabled, JQDIS must be set
+ (which can be done only if ADSTART and JADSTART are both cleared).
+ If JQDIS is not set at that point, returns an error
+ - since software trigger detection is disabled. User needs to
+ resort to HAL_ADCEx_DisableInjectedQueue() API to set JQDIS.
+ - or (if JQDIS is intentionally reset) since JEXTEN = 0 which means
+ the queue is empty */
+ tmp_config_injected_queue = READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS);
+
+ if ((READ_BIT(hadc->Instance->JSQR, ADC_JSQR_JEXTEN) == 0UL)
+ && (tmp_config_injected_queue == 0UL)
+ )
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_hal_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Check if a regular conversion is ongoing */
+ if ((hadc->State & HAL_ADC_STATE_REG_BUSY) != 0UL)
+ {
+ /* Reset ADC error code field related to injected conversions only */
+ CLEAR_BIT(hadc->ErrorCode, HAL_ADC_ERROR_JQOVF);
+ }
+ else
+ {
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Set ADC state */
+ /* - Clear state bitfield related to injected group conversion results */
+ /* - Set state bitfield related to injected operation */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_READY | HAL_ADC_STATE_INJ_EOC,
+ HAL_ADC_STATE_INJ_BUSY);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - if ADC instance is master or if multimode feature is not available
+ - if multimode setting is disabled (ADC instance slave in independent mode) */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ )
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* Clear ADC group injected group conversion flag */
+ /* (To ensure of no unknown state from potential previous ADC operations) */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_JEOC | ADC_FLAG_JEOS));
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* Enable ADC Injected context queue overflow interrupt if this feature */
+ /* is enabled. */
+ if ((hadc->Instance->CFGR & ADC_CFGR_JQM) != 0UL)
+ {
+ __HAL_ADC_ENABLE_IT(hadc, ADC_FLAG_JQOVF);
+ }
+
+ /* Enable ADC end of conversion interrupt */
+ switch (hadc->Init.EOCSelection)
+ {
+ case ADC_EOC_SEQ_CONV:
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC);
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOS);
+ break;
+ /* case ADC_EOC_SINGLE_CONV */
+ default:
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOS);
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);
+ break;
+ }
+
+ /* Enable conversion of injected group, if automatic injected conversion */
+ /* is disabled. */
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ /* Case of multimode enabled (when multimode feature is available): */
+ /* if ADC is slave, */
+ /* - ADC is enabled only (conversion is not started), */
+ /* - if multimode only concerns regular conversion, ADC is enabled */
+ /* and conversion is started. */
+ /* If ADC is master or independent, */
+ /* - ADC is enabled and conversion is started. */
+ if ((__LL_ADC_MULTI_INSTANCE_MASTER(hadc->Instance) == hadc->Instance)
+ || (tmp_multimode_config == LL_ADC_MULTI_INDEPENDENT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_REG_SIMULT)
+ || (tmp_multimode_config == LL_ADC_MULTI_DUAL_REG_INTERL)
+ )
+ {
+ /* ADC instance is not a multimode slave instance with multimode injected conversions enabled */
+ if (LL_ADC_INJ_GetTrigAuto(hadc->Instance) == LL_ADC_INJ_TRIG_INDEPENDENT)
+ {
+ LL_ADC_INJ_StartConversion(hadc->Instance);
+ }
+ }
+ else
+ {
+ /* ADC instance is not a multimode slave instance with multimode injected conversions enabled */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ /* Return function status */
+ return tmp_hal_status;
+ }
+}
+
+/**
+ * @brief Stop conversion of injected channels, disable interruption of
+ * end-of-conversion. Disable ADC peripheral if no regular conversion
+ * is on going.
+ * @note If ADC must be disabled and if conversion is on going on
+ * regular group, function HAL_ADC_Stop must be used to stop both
+ * injected and regular groups, and disable the ADC.
+ * @note If injected group mode auto-injection is enabled,
+ * function HAL_ADC_Stop must be used.
+ * @note Case of multimode enabled (when multimode feature is available):
+ * HAL_ADCEx_InjectedStop_IT() API must be called for ADC master first,
+ * then for ADC slave.
+ * For ADC master, conversion is stopped and ADC is disabled.
+ * For ADC slave, ADC is disabled only (conversion stop of ADC master
+ * has already stopped conversion of ADC slave).
+ * @note In case of auto-injection mode, HAL_ADC_Stop() must be used.
+ * @param hadc ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential conversion on going on injected group only. */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if injected conversions are effectively stopped */
+ /* and if no conversion on the other group (regular group) is intended to */
+ /* continue. */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Disable ADC end of conversion interrupt for injected channels */
+ __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_JEOC | ADC_IT_JEOS | ADC_FLAG_JQOVF));
+
+ if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* 2. Disable the ADC peripheral */
+ tmp_hal_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+ }
+ /* Conversion on injected group is stopped, but ADC not disabled since */
+ /* conversion on regular group is still running. */
+ else
+ {
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Enable ADC, start MultiMode conversion and transfer regular results through DMA.
+ * @note Multimode must have been previously configured using
+ * HAL_ADCEx_MultiModeConfigChannel() function.
+ * Interruptions enabled in this function:
+ * overrun, DMA half transfer, DMA transfer complete.
+ * Each of these interruptions has its dedicated callback function.
+ * @note State field of Slave ADC handle is not updated in this configuration:
+ * user should not rely on it for information related to Slave regular
+ * conversions.
+ * @param hadc ADC handle of ADC master (handle of ADC slave must not be used)
+ * @param pData Destination Buffer address.
+ * @param Length Length of data to be transferred from ADC peripheral to memory (in bytes).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ ADC_HandleTypeDef tmphadcSlave;
+ ADC_Common_TypeDef *tmpADC_Common;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_EXTTRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
+
+ if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) != 0UL)
+ {
+ return HAL_BUSY;
+ }
+ else
+ {
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Set a temporary handle of the ADC slave associated to the ADC master */
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ if (tmphadcSlave.Instance == NULL)
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the ADC peripherals: master and slave (in case if not already */
+ /* enabled previously) */
+ tmp_hal_status = ADC_Enable(hadc);
+ if (tmp_hal_status == HAL_OK)
+ {
+ tmp_hal_status = ADC_Enable(&tmphadcSlave);
+ }
+
+ /* Start multimode conversion of ADCs pair */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ (HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP),
+ HAL_ADC_STATE_REG_BUSY);
+
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+
+ /* Set the DMA transfer complete callback */
+ hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;
+
+ /* Set the DMA half transfer complete callback */
+ hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt;
+
+ /* Set the DMA error callback */
+ hadc->DMA_Handle->XferErrorCallback = ADC_DMAError ;
+
+ /* Pointer to the common control register */
+ tmpADC_Common = __LL_ADC_COMMON_INSTANCE(hadc->Instance);
+
+ /* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC */
+ /* start (in case of SW start): */
+
+ /* Clear regular group conversion flag and overrun flag */
+ /* (To ensure of no unknown state from potential previous ADC operations) */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS | ADC_FLAG_OVR));
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* Enable ADC overrun interrupt */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+
+ /* Start the DMA channel */
+ tmp_hal_status = HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&tmpADC_Common->CDR, (uint32_t)pData, Length);
+
+ /* Enable conversion of regular group. */
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ /* Start ADC group regular conversion */
+ LL_ADC_REG_StartConversion(hadc->Instance);
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ /* Return function status */
+ return tmp_hal_status;
+ }
+}
+
+/**
+ * @brief Stop multimode ADC conversion, disable ADC DMA transfer, disable ADC peripheral.
+ * @note Multimode is kept enabled after this function. MultiMode DMA bits
+ * (MDMA and DMACFG bits of common CCR register) are maintained. To disable
+ * Multimode (set with HAL_ADCEx_MultiModeConfigChannel()), ADC must be
+ * reinitialized using HAL_ADC_Init() or HAL_ADC_DeInit(), or the user can
+ * resort to HAL_ADCEx_DisableMultiMode() API.
+ * @note In case of DMA configured in circular mode, function
+ * HAL_ADC_Stop_DMA() must be called after this function with handle of
+ * ADC slave, to properly disable the DMA channel.
+ * @param hadc ADC handle of ADC master (handle of ADC slave must not be used)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ uint32_t tickstart;
+ ADC_HandleTypeDef tmphadcSlave;
+ uint32_t tmphadcSlave_conversion_on_going;
+ HAL_StatusTypeDef tmphadcSlave_disable_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+
+ /* 1. Stop potential multimode conversion on going, on regular and injected groups */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set a temporary handle of the ADC slave associated to the ADC master */
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ if (tmphadcSlave.Instance == NULL)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Procedure to disable the ADC peripheral: wait for conversions */
+ /* effectively stopped (ADC master and ADC slave), then disable ADC */
+
+ /* 1. Wait for ADC conversion completion for ADC master and ADC slave */
+ tickstart = HAL_GetTick();
+
+ tmphadcSlave_conversion_on_going = LL_ADC_REG_IsConversionOngoing((&tmphadcSlave)->Instance);
+ while ((LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 1UL)
+ || (tmphadcSlave_conversion_on_going == 1UL)
+ )
+ {
+ if ((HAL_GetTick() - tickstart) > ADC_STOP_CONVERSION_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ tmphadcSlave_conversion_on_going = LL_ADC_REG_IsConversionOngoing((&tmphadcSlave)->Instance);
+ }
+
+ /* Disable the DMA channel (in case of DMA in circular mode or stop */
+ /* while DMA transfer is on going) */
+ /* Note: DMA channel of ADC slave should be stopped after this function */
+ /* with HAL_ADC_Stop_DMA() API. */
+ tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Check if DMA channel effectively disabled */
+ if (tmp_hal_status == HAL_ERROR)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+ }
+
+ /* Disable ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+
+ /* 2. Disable the ADC peripherals: master and slave */
+ /* Update "tmp_hal_status" only if DMA channel disabling passed, to keep in */
+ /* memory a potential failing status. */
+ if (tmp_hal_status == HAL_OK)
+ {
+ tmphadcSlave_disable_status = ADC_Disable(&tmphadcSlave);
+ if ((ADC_Disable(hadc) == HAL_OK) &&
+ (tmphadcSlave_disable_status == HAL_OK))
+ {
+ tmp_hal_status = HAL_OK;
+ }
+ }
+ else
+ {
+ /* In case of error, attempt to disable ADC master and slave without status assert */
+ (void) ADC_Disable(hadc);
+ (void) ADC_Disable(&tmphadcSlave);
+ }
+
+ /* Set ADC state (ADC master) */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Return the last ADC Master and Slave regular conversions results when in multimode configuration.
+ * @param hadc ADC handle of ADC Master (handle of ADC Slave must not be used)
+ * @retval The converted data values.
+ */
+uint32_t HAL_ADCEx_MultiModeGetValue(ADC_HandleTypeDef *hadc)
+{
+ const ADC_Common_TypeDef *tmpADC_Common;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+
+ /* Prevent unused argument(s) compilation warning if no assert_param check */
+ /* and possible no usage in __LL_ADC_COMMON_INSTANCE() below */
+ UNUSED(hadc);
+
+ /* Pointer to the common control register */
+ tmpADC_Common = __LL_ADC_COMMON_INSTANCE(hadc->Instance);
+
+ /* Return the multi mode conversion value */
+ return tmpADC_Common->CDR;
+}
+
+/**
+ * @brief Get ADC injected group conversion result.
+ * @note Reading register JDRx automatically clears ADC flag JEOC
+ * (ADC group injected end of unitary conversion).
+ * @note This function does not clear ADC flag JEOS
+ * (ADC group injected end of sequence conversion)
+ * Occurrence of flag JEOS rising:
+ * - If sequencer is composed of 1 rank, flag JEOS is equivalent
+ * to flag JEOC.
+ * - If sequencer is composed of several ranks, during the scan
+ * sequence flag JEOC only is raised, at the end of the scan sequence
+ * both flags JEOC and EOS are raised.
+ * Flag JEOS must not be cleared by this function because
+ * it would not be compliant with low power features
+ * (feature low power auto-wait, not available on all STM32 families).
+ * To clear this flag, either use function:
+ * in programming model IT: @ref HAL_ADC_IRQHandler(), in programming
+ * model polling: @ref HAL_ADCEx_InjectedPollForConversion()
+ * or @ref __HAL_ADC_CLEAR_FLAG(&hadc, ADC_FLAG_JEOS).
+ * @param hadc ADC handle
+ * @param InjectedRank the converted ADC injected rank.
+ * This parameter can be one of the following values:
+ * @arg @ref ADC_INJECTED_RANK_1 ADC group injected rank 1
+ * @arg @ref ADC_INJECTED_RANK_2 ADC group injected rank 2
+ * @arg @ref ADC_INJECTED_RANK_3 ADC group injected rank 3
+ * @arg @ref ADC_INJECTED_RANK_4 ADC group injected rank 4
+ * @retval ADC group injected conversion data
+ */
+uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef *hadc, uint32_t InjectedRank)
+{
+ uint32_t tmp_jdr;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_INJECTED_RANK(InjectedRank));
+
+ /* Get ADC converted value */
+ switch (InjectedRank)
+ {
+ case ADC_INJECTED_RANK_4:
+ tmp_jdr = hadc->Instance->JDR4;
+ break;
+ case ADC_INJECTED_RANK_3:
+ tmp_jdr = hadc->Instance->JDR3;
+ break;
+ case ADC_INJECTED_RANK_2:
+ tmp_jdr = hadc->Instance->JDR2;
+ break;
+ case ADC_INJECTED_RANK_1:
+ default:
+ tmp_jdr = hadc->Instance->JDR1;
+ break;
+ }
+
+ /* Return ADC converted value */
+ return tmp_jdr;
+}
+
+/**
+ * @brief Injected conversion complete callback in non-blocking mode.
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADCEx_InjectedConvCpltCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Injected context queue overflow callback.
+ * @note This callback is called if injected context queue is enabled
+ (parameter "QueueInjectedContext" in injected channel configuration)
+ and if a new injected context is set when queue is full (maximum 2
+ contexts).
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADCEx_InjectedQueueOverflowCallback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADCEx_InjectedQueueOverflowCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Analog watchdog 2 callback in non-blocking mode.
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADCEx_LevelOutOfWindow2Callback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADCEx_LevelOutOfWindow2Callback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Analog watchdog 3 callback in non-blocking mode.
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADCEx_LevelOutOfWindow3Callback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADCEx_LevelOutOfWindow3Callback must be implemented in the user file.
+ */
+}
+
+
+/**
+ * @brief End Of Sampling callback in non-blocking mode.
+ * @param hadc ADC handle
+ * @retval None
+ */
+__weak void HAL_ADCEx_EndOfSamplingCallback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADCEx_EndOfSamplingCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Stop ADC conversion of regular group (and injected channels in
+ * case of auto_injection mode), disable ADC peripheral if no
+ * conversion is on going on injected group.
+ * @param hadc ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_RegularStop(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential regular conversion on going */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+
+ /* Disable ADC peripheral if regular conversions are effectively stopped
+ and if no injected conversions are on-going */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Clear HAL_ADC_STATE_REG_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* 2. Disable the ADC peripheral */
+ tmp_hal_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+ }
+ /* Conversion on injected group is stopped, but ADC not disabled since */
+ /* conversion on regular group is still running. */
+ else
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+
+/**
+ * @brief Stop ADC conversion of ADC groups regular and injected,
+ * disable interrution of end-of-conversion,
+ * disable ADC peripheral if no conversion is on going
+ * on injected group.
+ * @param hadc ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_RegularStop_IT(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential regular conversion on going */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped
+ and if no injected conversion is on-going */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Clear HAL_ADC_STATE_REG_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ /* Disable all regular-related interrupts */
+ __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_EOS | ADC_IT_OVR));
+
+ /* 2. Disable ADC peripheral if no injected conversions are on-going */
+ if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ tmp_hal_status = ADC_Disable(hadc);
+ /* if no issue reported */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+ }
+ else
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Stop ADC conversion of regular group (and injected group in
+ * case of auto_injection mode), disable ADC DMA transfer, disable
+ * ADC peripheral if no conversion is on going
+ * on injected group.
+ * @note HAL_ADCEx_RegularStop_DMA() function is dedicated to single-ADC mode only.
+ * For multimode (when multimode feature is available),
+ * HAL_ADCEx_RegularMultiModeStop_DMA() API must be used.
+ * @param hadc ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_RegularStop_DMA(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential regular conversion on going */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped
+ and if no injected conversion is on-going */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Clear HAL_ADC_STATE_REG_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ /* Disable ADC DMA (ADC DMA configuration ADC_CFGR_DMACFG is kept) */
+ MODIFY_REG(hadc->Instance->CFGR, ADC_CFGR_DMNGT_0 |ADC_CFGR_DMNGT_1, 0UL);
+
+ /* Disable the DMA channel (in case of DMA in circular mode or stop while */
+ /* while DMA transfer is on going) */
+ tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Check if DMA channel effectively disabled */
+ if (tmp_hal_status != HAL_OK)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+ }
+
+ /* Disable ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+
+ /* 2. Disable the ADC peripheral */
+ /* Update "tmp_hal_status" only if DMA channel disabling passed, */
+ /* to keep in memory a potential failing status. */
+ if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ if (tmp_hal_status == HAL_OK)
+ {
+ tmp_hal_status = ADC_Disable(hadc);
+ }
+ else
+ {
+ (void)ADC_Disable(hadc);
+ }
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+ }
+ else
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Stop DMA-based multimode ADC conversion, disable ADC DMA transfer, disable ADC peripheral if no injected conversion is on-going.
+ * @note Multimode is kept enabled after this function. Multimode DMA bits
+ * (MDMA and DMACFG bits of common CCR register) are maintained. To disable
+ * multimode (set with HAL_ADCEx_MultiModeConfigChannel()), ADC must be
+ * reinitialized using HAL_ADC_Init() or HAL_ADC_DeInit(), or the user can
+ * resort to HAL_ADCEx_DisableMultiMode() API.
+ * @note In case of DMA configured in circular mode, function
+ * HAL_ADCEx_RegularStop_DMA() must be called after this function with handle of
+ * ADC slave, to properly disable the DMA channel.
+ * @param hadc ADC handle of ADC master (handle of ADC slave must not be used)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_RegularMultiModeStop_DMA(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ uint32_t tickstart;
+ ADC_HandleTypeDef tmphadcSlave;
+ uint32_t tmphadcSlave_conversion_on_going;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+
+ /* 1. Stop potential multimode conversion on going, on regular groups */
+ tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Clear HAL_ADC_STATE_REG_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ /* Set a temporary handle of the ADC slave associated to the ADC master */
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ if (tmphadcSlave.Instance == NULL)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Procedure to disable the ADC peripheral: wait for conversions */
+ /* effectively stopped (ADC master and ADC slave), then disable ADC */
+
+ /* 1. Wait for ADC conversion completion for ADC master and ADC slave */
+ tickstart = HAL_GetTick();
+
+ tmphadcSlave_conversion_on_going = LL_ADC_REG_IsConversionOngoing((&tmphadcSlave)->Instance);
+ while ((LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 1UL)
+ || (tmphadcSlave_conversion_on_going == 1UL)
+ )
+ {
+ if ((HAL_GetTick() - tickstart) > ADC_STOP_CONVERSION_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ tmphadcSlave_conversion_on_going = LL_ADC_REG_IsConversionOngoing((&tmphadcSlave)->Instance);
+ }
+
+ /* Disable the DMA channel (in case of DMA in circular mode or stop */
+ /* while DMA transfer is on going) */
+ /* Note: DMA channel of ADC slave should be stopped after this function */
+ /* with HAL_ADCEx_RegularStop_DMA() API. */
+ tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Check if DMA channel effectively disabled */
+ if (tmp_hal_status != HAL_OK)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+ }
+
+ /* Disable ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+
+ /* 2. Disable the ADC peripherals: master and slave if no injected */
+ /* conversion is on-going. */
+ /* Update "tmp_hal_status" only if DMA channel disabling passed, to keep in */
+ /* memory a potential failing status. */
+ if (tmp_hal_status == HAL_OK)
+ {
+ if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ tmp_hal_status = ADC_Disable(hadc);
+ if (tmp_hal_status == HAL_OK)
+ {
+ if (LL_ADC_INJ_IsConversionOngoing((&tmphadcSlave)->Instance) == 0UL)
+ {
+ tmp_hal_status = ADC_Disable(&tmphadcSlave);
+ }
+ }
+ }
+
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Both Master and Slave ADC's could be disabled. Update Master State */
+ /* Clear HAL_ADC_STATE_INJ_BUSY bit, set HAL_ADC_STATE_READY bit */
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY, HAL_ADC_STATE_READY);
+ }
+ else
+ {
+ /* injected (Master or Slave) conversions are still on-going,
+ no Master State change */
+ }
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ADCEx_Exported_Functions_Group2 ADC Extended Peripheral Control functions
+ * @brief ADC Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure channels on injected group
+ (+) Configure multimode when multimode feature is available
+ (+) Enable or Disable Injected Queue
+ (+) Disable ADC voltage regulator
+ (+) Enter ADC deep-power-down mode
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure a channel to be assigned to ADC group injected.
+ * @note Possibility to update parameters on the fly:
+ * This function initializes injected group, following calls to this
+ * function can be used to reconfigure some parameters of structure
+ * "ADC_InjectionConfTypeDef" on the fly, without resetting the ADC.
+ * The setting of these parameters is conditioned to ADC state:
+ * Refer to comments of structure "ADC_InjectionConfTypeDef".
+ * @note In case of usage of internal measurement channels:
+ * Vbat/VrefInt/TempSensor.
+ * These internal paths can be disabled using function
+ * HAL_ADC_DeInit().
+ * @note Caution: For Injected Context Queue use, a context must be fully
+ * defined before start of injected conversion. All channels are configured
+ * consecutively for the same ADC instance. Therefore, the number of calls to
+ * HAL_ADCEx_InjectedConfigChannel() must be equal to the value of parameter
+ * InjectedNbrOfConversion for each context.
+ * - Example 1: If 1 context is intended to be used (or if there is no use of the
+ * Injected Queue Context feature) and if the context contains 3 injected ranks
+ * (InjectedNbrOfConversion = 3), HAL_ADCEx_InjectedConfigChannel() must be
+ * called once for each channel (i.e. 3 times) before starting a conversion.
+ * This function must not be called to configure a 4th injected channel:
+ * it would start a new context into context queue.
+ * - Example 2: If 2 contexts are intended to be used and each of them contains
+ * 3 injected ranks (InjectedNbrOfConversion = 3),
+ * HAL_ADCEx_InjectedConfigChannel() must be called once for each channel and
+ * for each context (3 channels x 2 contexts = 6 calls). Conversion can
+ * start once the 1st context is set, that is after the first three
+ * HAL_ADCEx_InjectedConfigChannel() calls. The 2nd context can be set on the fly.
+ * @param hadc ADC handle
+ * @param sConfigInjected Structure of ADC injected group and ADC channel for
+ * injected group.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef *hadc, ADC_InjectionConfTypeDef *sConfigInjected)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ uint32_t tmpOffsetShifted;
+ uint32_t tmp_config_internal_channel;
+ uint32_t tmp_adc_is_conversion_on_going_regular;
+ uint32_t tmp_adc_is_conversion_on_going_injected;
+ __IO uint32_t wait_loop_index = 0;
+
+ uint32_t tmp_JSQR_ContextQueueBeingBuilt = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_SAMPLE_TIME(sConfigInjected->InjectedSamplingTime));
+ assert_param(IS_ADC_SINGLE_DIFFERENTIAL(sConfigInjected->InjectedSingleDiff));
+ assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->AutoInjectedConv));
+ assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->QueueInjectedContext));
+ assert_param(IS_ADC_EXTTRIGINJEC_EDGE(sConfigInjected->ExternalTrigInjecConvEdge));
+ assert_param(IS_ADC_EXTTRIGINJEC(sConfigInjected->ExternalTrigInjecConv));
+ assert_param(IS_ADC_OFFSET_NUMBER(sConfigInjected->InjectedOffsetNumber));
+ assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), sConfigInjected->InjectedOffset));
+ assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->InjecOversamplingMode));
+
+ if (hadc->Init.ScanConvMode != ADC_SCAN_DISABLE)
+ {
+ assert_param(IS_ADC_INJECTED_RANK(sConfigInjected->InjectedRank));
+ assert_param(IS_ADC_INJECTED_NB_CONV(sConfigInjected->InjectedNbrOfConversion));
+ assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->InjectedDiscontinuousConvMode));
+ }
+
+ /* Check offset range according to oversampling setting */
+ if (hadc->Init.OversamplingMode == ENABLE)
+ {
+ assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), sConfigInjected->InjectedOffset/(hadc->Init.Oversampling.Ratio+1U)));
+ }
+ else
+ {
+ assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), sConfigInjected->InjectedOffset));
+ }
+
+ /* JDISCEN and JAUTO bits can't be set at the same time */
+ assert_param(!((sConfigInjected->InjectedDiscontinuousConvMode == ENABLE) && (sConfigInjected->AutoInjectedConv == ENABLE)));
+
+ /* DISCEN and JAUTO bits can't be set at the same time */
+ assert_param(!((hadc->Init.DiscontinuousConvMode == ENABLE) && (sConfigInjected->AutoInjectedConv == ENABLE)));
+
+ /* Verification of channel number */
+ if (sConfigInjected->InjectedSingleDiff != ADC_DIFFERENTIAL_ENDED)
+ {
+ assert_param(IS_ADC_CHANNEL(sConfigInjected->InjectedChannel));
+ }
+ else
+ {
+ if (hadc->Instance == ADC1)
+ {
+ assert_param(IS_ADC1_DIFF_CHANNEL(sConfigInjected->InjectedChannel));
+ }
+ if (hadc->Instance == ADC2)
+ {
+ assert_param(IS_ADC2_DIFF_CHANNEL(sConfigInjected->InjectedChannel));
+ }
+#if defined (ADC3)
+ if (hadc->Instance == ADC3)
+ {
+ assert_param(IS_ADC3_DIFF_CHANNEL(sConfigInjected->InjectedChannel));
+ }
+#endif
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Configuration of injected group sequencer: */
+ /* Hardware constraint: Must fully define injected context register JSQR */
+ /* before make it entering into injected sequencer queue. */
+ /* */
+ /* - if scan mode is disabled: */
+ /* * Injected channels sequence length is set to 0x00: 1 channel */
+ /* converted (channel on injected rank 1) */
+ /* Parameter "InjectedNbrOfConversion" is discarded. */
+ /* * Injected context register JSQR setting is simple: register is fully */
+ /* defined on one call of this function (for injected rank 1) and can */
+ /* be entered into queue directly. */
+ /* - if scan mode is enabled: */
+ /* * Injected channels sequence length is set to parameter */
+ /* "InjectedNbrOfConversion". */
+ /* * Injected context register JSQR setting more complex: register is */
+ /* fully defined over successive calls of this function, for each */
+ /* injected channel rank. It is entered into queue only when all */
+ /* injected ranks have been set. */
+ /* Note: Scan mode is not present by hardware on this device, but used */
+ /* by software for alignment over all STM32 devices. */
+
+ if ((hadc->Init.ScanConvMode == ADC_SCAN_DISABLE) ||
+ (sConfigInjected->InjectedNbrOfConversion == 1U))
+ {
+ /* Configuration of context register JSQR: */
+ /* - number of ranks in injected group sequencer: fixed to 1st rank */
+ /* (scan mode disabled, only rank 1 used) */
+ /* - external trigger to start conversion */
+ /* - external trigger polarity */
+ /* - channel set to rank 1 (scan mode disabled, only rank 1 can be used) */
+
+ if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1)
+ {
+ /* Enable external trigger if trigger selection is different of */
+ /* software start. */
+ /* Note: This configuration keeps the hardware feature of parameter */
+ /* ExternalTrigInjecConvEdge "trigger edge none" equivalent to */
+ /* software start. */
+ if (sConfigInjected->ExternalTrigInjecConv != ADC_INJECTED_SOFTWARE_START)
+ {
+ tmp_JSQR_ContextQueueBeingBuilt = (ADC_JSQR_RK(sConfigInjected->InjectedChannel, ADC_INJECTED_RANK_1)
+ | (sConfigInjected->ExternalTrigInjecConv & ADC_JSQR_JEXTSEL)
+ | sConfigInjected->ExternalTrigInjecConvEdge
+ );
+ }
+ else
+ {
+ tmp_JSQR_ContextQueueBeingBuilt = (ADC_JSQR_RK(sConfigInjected->InjectedChannel, ADC_INJECTED_RANK_1));
+ }
+
+ MODIFY_REG(hadc->Instance->JSQR, ADC_JSQR_FIELDS, tmp_JSQR_ContextQueueBeingBuilt);
+ /* For debug and informative reasons, hadc handle saves JSQR setting */
+ hadc->InjectionConfig.ContextQueue = tmp_JSQR_ContextQueueBeingBuilt;
+
+ }
+ }
+ else
+ {
+ /* Case of scan mode enabled, several channels to set into injected group */
+ /* sequencer. */
+ /* */
+ /* Procedure to define injected context register JSQR over successive */
+ /* calls of this function, for each injected channel rank: */
+ /* 1. Start new context and set parameters related to all injected */
+ /* channels: injected sequence length and trigger. */
+
+ /* if hadc->InjectionConfig.ChannelCount is equal to 0, this is the first */
+ /* call of the context under setting */
+ if (hadc->InjectionConfig.ChannelCount == 0U)
+ {
+ /* Initialize number of channels that will be configured on the context */
+ /* being built */
+ hadc->InjectionConfig.ChannelCount = sConfigInjected->InjectedNbrOfConversion;
+ /* Handle hadc saves the context under build up over each HAL_ADCEx_InjectedConfigChannel()
+ call, this context will be written in JSQR register at the last call.
+ At this point, the context is merely reset */
+ hadc->InjectionConfig.ContextQueue = 0x00000000U;
+
+ /* Configuration of context register JSQR: */
+ /* - number of ranks in injected group sequencer */
+ /* - external trigger to start conversion */
+ /* - external trigger polarity */
+
+ /* Enable external trigger if trigger selection is different of */
+ /* software start. */
+ /* Note: This configuration keeps the hardware feature of parameter */
+ /* ExternalTrigInjecConvEdge "trigger edge none" equivalent to */
+ /* software start. */
+ if (sConfigInjected->ExternalTrigInjecConv != ADC_INJECTED_SOFTWARE_START)
+ {
+ tmp_JSQR_ContextQueueBeingBuilt = ((sConfigInjected->InjectedNbrOfConversion - 1U)
+ | (sConfigInjected->ExternalTrigInjecConv & ADC_JSQR_JEXTSEL)
+ | sConfigInjected->ExternalTrigInjecConvEdge
+ );
+ }
+ else
+ {
+ tmp_JSQR_ContextQueueBeingBuilt = ((sConfigInjected->InjectedNbrOfConversion - 1U));
+ }
+
+ }
+
+ /* 2. Continue setting of context under definition with parameter */
+ /* related to each channel: channel rank sequence */
+ /* Clear the old JSQx bits for the selected rank */
+ tmp_JSQR_ContextQueueBeingBuilt &= ~ADC_JSQR_RK(ADC_SQR3_SQ10, sConfigInjected->InjectedRank);
+
+ /* Set the JSQx bits for the selected rank */
+ tmp_JSQR_ContextQueueBeingBuilt |= ADC_JSQR_RK(sConfigInjected->InjectedChannel, sConfigInjected->InjectedRank);
+
+ /* Decrease channel count */
+ hadc->InjectionConfig.ChannelCount--;
+
+ /* 3. tmp_JSQR_ContextQueueBeingBuilt is fully built for this HAL_ADCEx_InjectedConfigChannel()
+ call, aggregate the setting to those already built during the previous
+ HAL_ADCEx_InjectedConfigChannel() calls (for the same context of course) */
+ hadc->InjectionConfig.ContextQueue |= tmp_JSQR_ContextQueueBeingBuilt;
+
+ /* 4. End of context setting: if this is the last channel set, then write context
+ into register JSQR and make it enter into queue */
+ if (hadc->InjectionConfig.ChannelCount == 0U)
+ {
+ MODIFY_REG(hadc->Instance->JSQR, ADC_JSQR_FIELDS, hadc->InjectionConfig.ContextQueue);
+ }
+ }
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated when ADC is disabled or enabled without */
+ /* conversion on going on injected group: */
+ /* - Injected context queue: Queue disable (active context is kept) or */
+ /* enable (context decremented, up to 2 contexts queued) */
+ /* - Injected discontinuous mode: can be enabled only if auto-injected */
+ /* mode is disabled. */
+ if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+ {
+ /* ADC channels preselection */
+ hadc->Instance->PCSEL |= (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfigInjected->InjectedChannel) & 0x1FUL));
+
+ /* If auto-injected mode is disabled: no constraint */
+ if (sConfigInjected->AutoInjectedConv == DISABLE)
+ {
+ MODIFY_REG(hadc->Instance->CFGR,
+ ADC_CFGR_JQM | ADC_CFGR_JDISCEN,
+ ADC_CFGR_INJECT_CONTEXT_QUEUE((uint32_t)sConfigInjected->QueueInjectedContext) |
+ ADC_CFGR_INJECT_DISCCONTINUOUS((uint32_t)sConfigInjected->InjectedDiscontinuousConvMode));
+ }
+ /* If auto-injected mode is enabled: Injected discontinuous setting is */
+ /* discarded. */
+ else
+ {
+ MODIFY_REG(hadc->Instance->CFGR,
+ ADC_CFGR_JQM | ADC_CFGR_JDISCEN,
+ ADC_CFGR_INJECT_CONTEXT_QUEUE((uint32_t)sConfigInjected->QueueInjectedContext));
+ }
+
+ }
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated when ADC is disabled or enabled without */
+ /* conversion on going on regular and injected groups: */
+ /* - Automatic injected conversion: can be enabled if injected group */
+ /* external triggers are disabled. */
+ /* - Channel sampling time */
+ /* - Channel offset */
+ tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+ tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+
+ if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+ && (tmp_adc_is_conversion_on_going_injected == 0UL)
+ )
+ {
+ /* If injected group external triggers are disabled (set to injected */
+ /* software start): no constraint */
+ if ((sConfigInjected->ExternalTrigInjecConv == ADC_INJECTED_SOFTWARE_START)
+ || (sConfigInjected->ExternalTrigInjecConvEdge == ADC_EXTERNALTRIGINJECCONV_EDGE_NONE))
+ {
+ if (sConfigInjected->AutoInjectedConv == ENABLE)
+ {
+ SET_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO);
+ }
+ else
+ {
+ CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO);
+ }
+ }
+ /* If Automatic injected conversion was intended to be set and could not */
+ /* due to injected group external triggers enabled, error is reported. */
+ else
+ {
+ if (sConfigInjected->AutoInjectedConv == ENABLE)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+ else
+ {
+ CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO);
+ }
+ }
+
+ if (sConfigInjected->InjecOversamplingMode == ENABLE)
+ {
+ assert_param(IS_ADC_OVERSAMPLING_RATIO(sConfigInjected->InjecOversampling.Ratio));
+ assert_param(IS_ADC_RIGHT_BIT_SHIFT(sConfigInjected->InjecOversampling.RightBitShift));
+
+ /* JOVSE must be reset in case of triggered regular mode */
+ assert_param(!(READ_BIT(hadc->Instance->CFGR2, ADC_CFGR2_ROVSE | ADC_CFGR2_TROVS) == (ADC_CFGR2_ROVSE | ADC_CFGR2_TROVS)));
+
+ /* Configuration of Injected Oversampler: */
+ /* - Oversampling Ratio */
+ /* - Right bit shift */
+
+ /* Enable OverSampling mode */
+ MODIFY_REG(hadc->Instance->CFGR2,
+ ADC_CFGR2_JOVSE |
+ ADC_CFGR2_OVSR |
+ ADC_CFGR2_OVSS,
+ ADC_CFGR2_JOVSE |
+ ((sConfigInjected->InjecOversampling.Ratio - 1UL) << ADC_CFGR2_OVSR_Pos) |
+ sConfigInjected->InjecOversampling.RightBitShift
+ );
+ }
+ else
+ {
+ /* Disable Regular OverSampling */
+ CLEAR_BIT(hadc->Instance->CFGR2, ADC_CFGR2_JOVSE);
+ }
+
+ /* Set sampling time of the selected ADC channel */
+ LL_ADC_SetChannelSamplingTime(hadc->Instance, sConfigInjected->InjectedChannel, sConfigInjected->InjectedSamplingTime);
+
+ /* Configure the offset: offset enable/disable, channel, offset value */
+
+ /* Shift the offset with respect to the selected ADC resolution. */
+ /* Offset has to be left-aligned on bit 11, the LSB (right bits) are set to 0 */
+ tmpOffsetShifted = ADC_OFFSET_SHIFT_RESOLUTION(hadc, sConfigInjected->InjectedOffset);
+
+ if (sConfigInjected->InjectedOffsetNumber != ADC_OFFSET_NONE)
+ {
+ /* Set ADC selected offset number */
+ LL_ADC_SetOffset(hadc->Instance, sConfigInjected->InjectedOffsetNumber, sConfigInjected->InjectedChannel,
+ tmpOffsetShifted);
+
+ /* Set ADC selected offset signed saturation */
+ LL_ADC_SetOffsetSignedSaturation(hadc->Instance, sConfigInjected->InjectedOffsetNumber, (sConfigInjected->InjectedOffsetSignedSaturation == ENABLE) ? LL_ADC_OFFSET_SIGNED_SATURATION_ENABLE : LL_ADC_OFFSET_SIGNED_SATURATION_DISABLE);
+
+ /* Set ADC selected offset right shift */
+ LL_ADC_SetDataRightShift(hadc->Instance, sConfigInjected->InjectedOffsetNumber, (sConfigInjected->InjectedOffsetRightShift == (uint32_t)ENABLE) ? LL_ADC_OFFSET_RSHIFT_ENABLE : LL_ADC_OFFSET_RSHIFT_DISABLE);
+
+ }
+ else
+ {
+ /* Scan each offset register to check if the selected channel is targeted. */
+ /* If this is the case, the corresponding offset number is disabled. */
+ if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_1)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfigInjected->InjectedChannel))
+ {
+ LL_ADC_SetOffset(hadc->Instance, LL_ADC_OFFSET_1, sConfigInjected->InjectedChannel, LL_ADC_OFFSET_SIGNED_SATURATION_DISABLE);
+ }
+ if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_2)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfigInjected->InjectedChannel))
+ {
+ LL_ADC_SetOffset(hadc->Instance, LL_ADC_OFFSET_2, sConfigInjected->InjectedChannel, LL_ADC_OFFSET_SIGNED_SATURATION_DISABLE);
+ }
+ if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_3)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfigInjected->InjectedChannel))
+ {
+ LL_ADC_SetOffset(hadc->Instance, LL_ADC_OFFSET_4, sConfigInjected->InjectedChannel, LL_ADC_OFFSET_SIGNED_SATURATION_DISABLE);
+ }
+ if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_4)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfigInjected->InjectedChannel))
+ {
+ LL_ADC_SetOffset(hadc->Instance, LL_ADC_OFFSET_4, sConfigInjected->InjectedChannel, LL_ADC_OFFSET_SIGNED_SATURATION_DISABLE);
+ }
+ }
+
+ }
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated only when ADC is disabled: */
+ /* - Single or differential mode */
+ /* - Internal measurement channels: Vbat/VrefInt/TempSensor */
+ if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+ {
+ /* Set mode single-ended or differential input of the selected ADC channel */
+ LL_ADC_SetChannelSingleDiff(hadc->Instance, sConfigInjected->InjectedChannel, sConfigInjected->InjectedSingleDiff);
+
+ /* Configuration of differential mode */
+ /* Note: ADC channel number masked with value "0x1F" to ensure shift value within 32 bits range */
+ if (sConfigInjected->InjectedSingleDiff == ADC_DIFFERENTIAL_ENDED)
+ {
+ /* Set sampling time of the selected ADC channel */
+ LL_ADC_SetChannelSamplingTime(hadc->Instance, (uint32_t)(__LL_ADC_DECIMAL_NB_TO_CHANNEL((__LL_ADC_CHANNEL_TO_DECIMAL_NB((uint32_t)sConfigInjected->InjectedChannel) + 1UL) & 0x1FUL)), sConfigInjected->InjectedSamplingTime);
+ }
+
+ /* Management of internal measurement channels: Vbat/VrefInt/TempSensor */
+ /* internal measurement paths enable: If internal channel selected, */
+ /* enable dedicated internal buffers and path. */
+ /* Note: these internal measurement paths can be disabled using */
+ /* HAL_ADC_DeInit(). */
+
+ if(__LL_ADC_IS_CHANNEL_INTERNAL(sConfigInjected->InjectedChannel))
+ {
+ /* Configuration of common ADC parameters (continuation) */
+ /* Software is allowed to change common parameters only when all ADCs */
+ /* of the common group are disabled. */
+ if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+ {
+ tmp_config_internal_channel = LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+ /* If the requested internal measurement path has already been enabled, */
+ /* bypass the configuration processing. */
+ if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_TEMPSENSOR) == 0UL))
+ {
+ if (ADC_TEMPERATURE_SENSOR_INSTANCE(hadc))
+ {
+ LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_TEMPSENSOR | tmp_config_internal_channel);
+
+ /* Delay for temperature sensor stabilization time */
+ /* Wait loop initialization and execution */
+ /* Note: Variable divided by 2 to compensate partially */
+ /* CPU processing cycles, scaling in us split to not */
+ /* exceed 32 bits register capacity and handle low frequency. */
+ wait_loop_index = ((LL_ADC_DELAY_TEMPSENSOR_STAB_US / 10UL) * (SystemCoreClock / (100000UL * 2UL)));
+ while(wait_loop_index != 0UL)
+ {
+ wait_loop_index--;
+ }
+ }
+ }
+ else if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VBAT) == 0UL))
+ {
+ if (ADC_BATTERY_VOLTAGE_INSTANCE(hadc))
+ {
+ LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VBAT | tmp_config_internal_channel);
+ }
+ }
+ else if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VREFINT) == 0UL))
+ {
+ if (ADC_VREFINT_INSTANCE(hadc))
+ {
+ LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VREFINT | tmp_config_internal_channel);
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ }
+ /* If the requested internal measurement path has already been enabled */
+ /* and other ADC of the common group are enabled, internal */
+ /* measurement paths cannot be enabled. */
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+ }
+
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Enable ADC multimode and configure multimode parameters
+ * @note Possibility to update parameters on the fly:
+ * This function initializes multimode parameters, following
+ * calls to this function can be used to reconfigure some parameters
+ * of structure "ADC_MultiModeTypeDef" on the fly, without resetting
+ * the ADCs.
+ * The setting of these parameters is conditioned to ADC state.
+ * For parameters constraints, see comments of structure
+ * "ADC_MultiModeTypeDef".
+ * @note To move back configuration from multimode to single mode, ADC must
+ * be reset (using function HAL_ADC_Init() ).
+ * @param hadc Master ADC handle
+ * @param multimode Structure of ADC multimode configuration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeConfigChannel(ADC_HandleTypeDef *hadc, ADC_MultiModeTypeDef *multimode)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ ADC_Common_TypeDef *tmpADC_Common;
+ ADC_HandleTypeDef tmphadcSlave;
+ uint32_t tmphadcSlave_conversion_on_going;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_MULTIMODE(multimode->Mode));
+ if (multimode->Mode != ADC_MODE_INDEPENDENT)
+ {
+ assert_param(IS_ADC_DUAL_DATA_MODE(multimode->DualModeData));
+ assert_param(IS_ADC_SAMPLING_DELAY(multimode->TwoSamplingDelay));
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ if (tmphadcSlave.Instance == NULL)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated when ADC is disabled or enabled without */
+ /* conversion on going on regular group: */
+ /* - Multimode DATA Format configuration */
+ tmphadcSlave_conversion_on_going = LL_ADC_REG_IsConversionOngoing((&tmphadcSlave)->Instance);
+ if ((LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+ && (tmphadcSlave_conversion_on_going == 0UL))
+ {
+ /* Pointer to the common control register */
+ tmpADC_Common = __LL_ADC_COMMON_INSTANCE(hadc->Instance);
+
+ /* If multimode is selected, configure all multimode parameters. */
+ /* Otherwise, reset multimode parameters (can be used in case of */
+ /* transition from multimode to independent mode). */
+ if (multimode->Mode != ADC_MODE_INDEPENDENT)
+ {
+ MODIFY_REG(tmpADC_Common->CCR, ADC_CCR_DAMDF, multimode->DualModeData);
+
+ /* Parameters that can be updated only when ADC is disabled: */
+ /* - Multimode mode selection */
+ /* - Multimode delay */
+ /* Note: Delay range depends on selected resolution: */
+ /* from 1 to 9 clock cycles for 16 bits */
+ /* from 1 to 9 clock cycles for 14 bits, */
+ /* from 1 to 8 clock cycles for 12 bits */
+ /* from 1 to 6 clock cycles for 10 and 8 bits */
+ /* If a higher delay is selected, it will be clipped to maximum delay */
+ /* range */
+
+ if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+ {
+ MODIFY_REG(tmpADC_Common->CCR,
+ ADC_CCR_DUAL |
+ ADC_CCR_DELAY,
+ multimode->Mode |
+ multimode->TwoSamplingDelay
+ );
+ }
+ }
+ else /* ADC_MODE_INDEPENDENT */
+ {
+ CLEAR_BIT(tmpADC_Common->CCR, ADC_CCR_DAMDF);
+
+ /* Parameters that can be updated only when ADC is disabled: */
+ /* - Multimode mode selection */
+ /* - Multimode delay */
+ if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+ {
+ CLEAR_BIT(tmpADC_Common->CCR, ADC_CCR_DUAL | ADC_CCR_DELAY);
+ }
+ }
+ }
+ /* If one of the ADC sharing the same common group is enabled, no update */
+ /* could be done on neither of the multimode structure parameters. */
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Enable Injected Queue
+ * @note This function resets CFGR register JQDIS bit in order to enable the
+ * Injected Queue. JQDIS can be written only when ADSTART and JDSTART
+ * are both equal to 0 to ensure that no regular nor injected
+ * conversion is ongoing.
+ * @param hadc ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_EnableInjectedQueue(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ uint32_t tmp_adc_is_conversion_on_going_regular;
+ uint32_t tmp_adc_is_conversion_on_going_injected;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+ tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+
+ /* Parameter can be set only if no conversion is on-going */
+ if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+ && (tmp_adc_is_conversion_on_going_injected == 0UL)
+ )
+ {
+ CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS);
+
+ /* Update state, clear previous result related to injected queue overflow */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_JQOVF);
+
+ tmp_hal_status = HAL_OK;
+ }
+ else
+ {
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Disable Injected Queue
+ * @note This function sets CFGR register JQDIS bit in order to disable the
+ * Injected Queue. JQDIS can be written only when ADSTART and JDSTART
+ * are both equal to 0 to ensure that no regular nor injected
+ * conversion is ongoing.
+ * @param hadc ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_DisableInjectedQueue(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+ uint32_t tmp_adc_is_conversion_on_going_regular;
+ uint32_t tmp_adc_is_conversion_on_going_injected;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+ tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+
+ /* Parameter can be set only if no conversion is on-going */
+ if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+ && (tmp_adc_is_conversion_on_going_injected == 0UL)
+ )
+ {
+ LL_ADC_INJ_SetQueueMode(hadc->Instance, LL_ADC_INJ_QUEUE_DISABLE);
+ tmp_hal_status = HAL_OK;
+ }
+ else
+ {
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Disable ADC voltage regulator.
+ * @note Disabling voltage regulator allows to save power. This operation can
+ * be carried out only when ADC is disabled.
+ * @note To enable again the voltage regulator, the user is expected to
+ * resort to HAL_ADC_Init() API.
+ * @param hadc ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_DisableVoltageRegulator(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Setting of this feature is conditioned to ADC state: ADC must be ADC disabled */
+ if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+ {
+ LL_ADC_DisableInternalRegulator(hadc->Instance);
+ tmp_hal_status = HAL_OK;
+ }
+ else
+ {
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Enter ADC deep-power-down mode
+ * @note This mode is achieved in setting DEEPPWD bit and allows to save power
+ * in reducing leakage currents. It is particularly interesting before
+ * entering stop modes.
+ * @note Setting DEEPPWD automatically clears ADVREGEN bit and disables the
+ * ADC voltage regulator. This means that this API encompasses
+ * HAL_ADCEx_DisableVoltageRegulator(). Additionally, the internal
+ * calibration is lost.
+ * @note To exit the ADC deep-power-down mode, the user is expected to
+ * resort to HAL_ADC_Init() API as well as to relaunch a calibration
+ * with HAL_ADCEx_Calibration_Start() API or to re-apply a previously
+ * saved calibration factor.
+ * @param hadc ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_EnterADCDeepPowerDownMode(ADC_HandleTypeDef *hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Setting of this feature is conditioned to ADC state: ADC must be ADC disabled */
+ if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+ {
+ LL_ADC_EnableDeepPowerDown(hadc->Instance);
+ tmp_hal_status = HAL_OK;
+ }
+ else
+ {
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ return tmp_hal_status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_cec.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_cec.c
new file mode 100644
index 0000000000..1b87bac84e
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_cec.c
@@ -0,0 +1,1001 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_cec.c
+ * @author MCD Application Team
+ * @brief CEC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the High Definition Multimedia Interface
+ * Consumer Electronics Control Peripheral (CEC).
+ * + Initialization and de-initialization function
+ * + IO operation function
+ * + Peripheral Control function
+ *
+ *
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The CEC HAL driver can be used as follow:
+
+ (#) Declare a CEC_HandleTypeDef handle structure.
+ (#) Initialize the CEC low level resources by implementing the HAL_CEC_MspInit ()API:
+ (##) Enable the CEC interface clock.
+ (##) CEC pins configuration:
+ (+++) Enable the clock for the CEC GPIOs.
+ (+++) Configure these CEC pins as alternate function pull-up.
+ (##) NVIC configuration if you need to use interrupt process (HAL_CEC_Transmit_IT()
+ and HAL_CEC_Receive_IT() APIs):
+ (+++) Configure the CEC interrupt priority.
+ (+++) Enable the NVIC CEC IRQ handle.
+ (+++) The specific CEC interrupts (Transmission complete interrupt,
+ RXNE interrupt and Error Interrupts) will be managed using the macros
+ __HAL_CEC_ENABLE_IT() and __HAL_CEC_DISABLE_IT() inside the transmit
+ and receive process.
+
+ (#) Program the Signal Free Time (SFT) and SFT option, Tolerance, reception stop in
+ in case of Bit Rising Error, Error-Bit generation conditions, device logical
+ address and Listen mode in the hcec Init structure.
+
+ (#) Initialize the CEC registers by calling the HAL_CEC_Init() API.
+
+ [..]
+ (@) This API (HAL_CEC_Init()) configures also the low level Hardware (GPIO, CLOCK, CORTEX...etc)
+ by calling the customed HAL_CEC_MspInit() API.
+ *** Callback registration ***
+ =============================================
+
+ The compilation define USE_HAL_CEC_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions @ref HAL_CEC_RegisterCallback() or HAL_CEC_RegisterXXXCallback()
+ to register an interrupt callback.
+
+ Function @ref HAL_CEC_RegisterCallback() allows to register following callbacks:
+ (+) TxCpltCallback : Tx Transfer completed callback.
+ (+) ErrorCallback : callback for error detection.
+ (+) MspInitCallback : CEC MspInit.
+ (+) MspDeInitCallback : CEC MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ For specific callback HAL_CEC_RxCpltCallback use dedicated register callbacks
+ @ref HAL_CEC_RegisterRxCpltCallback().
+
+ Use function @ref HAL_CEC_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ @ref HAL_CEC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxCpltCallback : Tx Transfer completed callback.
+ (+) ErrorCallback : callback for error detection.
+ (+) MspInitCallback : CEC MspInit.
+ (+) MspDeInitCallback : CEC MspDeInit.
+
+ For callback HAL_CEC_RxCpltCallback use dedicated unregister callback :
+ @ref HAL_CEC_UnRegisterRxCpltCallback().
+
+ By default, after the @ref HAL_CEC_Init() and when the state is HAL_CEC_STATE_RESET
+ all callbacks are set to the corresponding weak functions :
+ examples @ref HAL_CEC_TxCpltCallback() , @ref HAL_CEC_RxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak function in the @ref HAL_CEC_Init()/ @ref HAL_CEC_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ if not, MspInit or MspDeInit are not null, the @ref HAL_CEC_Init() / @ref HAL_CEC_DeInit()
+ keep and use the user MspInit/MspDeInit functions (registered beforehand)
+
+ Callbacks can be registered/unregistered in HAL_CEC_STATE_READY state only.
+ Exception done MspInit/MspDeInit callbacks that can be registered/unregistered
+ in HAL_CEC_STATE_READY or HAL_CEC_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 @ref HAL_CEC_RegisterCallback() before calling @ref HAL_CEC_DeInit()
+ or @ref HAL_CEC_Init() function.
+
+ When the compilation define USE_HAL_CEC_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup CEC CEC
+ * @brief HAL CEC module driver
+ * @{
+ */
+#ifdef HAL_CEC_MODULE_ENABLED
+#if defined (CEC)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup CEC_Private_Constants CEC Private Constants
+ * @{
+ */
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup CEC_Private_Functions CEC Private Functions
+ * @{
+ */
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+
+/** @defgroup CEC_Exported_Functions CEC Exported Functions
+ * @{
+ */
+
+/** @defgroup CEC_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to initialize the CEC
+ (+) The following parameters need to be configured:
+ (++) SignalFreeTime
+ (++) Tolerance
+ (++) BRERxStop (RX stopped or not upon Bit Rising Error)
+ (++) BREErrorBitGen (Error-Bit generation in case of Bit Rising Error)
+ (++) LBPEErrorBitGen (Error-Bit generation in case of Long Bit Period Error)
+ (++) BroadcastMsgNoErrorBitGen (Error-bit generation in case of broadcast message error)
+ (++) SignalFreeTimeOption (SFT Timer start definition)
+ (++) OwnAddress (CEC device address)
+ (++) ListenMode
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the CEC mode according to the specified
+ * parameters in the CEC_InitTypeDef and creates the associated handle .
+ * @param hcec CEC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CEC_Init(CEC_HandleTypeDef *hcec)
+{
+ /* Check the CEC handle allocation */
+ if ((hcec == NULL) || (hcec->Init.RxBuffer == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
+ assert_param(IS_CEC_SIGNALFREETIME(hcec->Init.SignalFreeTime));
+ assert_param(IS_CEC_TOLERANCE(hcec->Init.Tolerance));
+ assert_param(IS_CEC_BRERXSTOP(hcec->Init.BRERxStop));
+ assert_param(IS_CEC_BREERRORBITGEN(hcec->Init.BREErrorBitGen));
+ assert_param(IS_CEC_LBPEERRORBITGEN(hcec->Init.LBPEErrorBitGen));
+ assert_param(IS_CEC_BROADCASTERROR_NO_ERRORBIT_GENERATION(hcec->Init.BroadcastMsgNoErrorBitGen));
+ assert_param(IS_CEC_SFTOP(hcec->Init.SignalFreeTimeOption));
+ assert_param(IS_CEC_LISTENING_MODE(hcec->Init.ListenMode));
+ assert_param(IS_CEC_OWN_ADDRESS(hcec->Init.OwnAddress));
+
+#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
+ if (hcec->gState == HAL_CEC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hcec->Lock = HAL_UNLOCKED;
+
+ hcec->TxCpltCallback = HAL_CEC_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ hcec->ErrorCallback = HAL_CEC_ErrorCallback; /* Legacy weak ErrorCallback */
+
+ if (hcec->MspInitCallback == NULL)
+ {
+ hcec->MspInitCallback = HAL_CEC_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware */
+ hcec->MspInitCallback(hcec);
+ }
+#else
+ if (hcec->gState == HAL_CEC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hcec->Lock = HAL_UNLOCKED;
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_CEC_MspInit(hcec);
+ }
+#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
+
+ hcec->gState = HAL_CEC_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_CEC_DISABLE(hcec);
+
+ /* Write to CEC Control Register */
+ hcec->Instance->CFGR = hcec->Init.SignalFreeTime | hcec->Init.Tolerance | hcec->Init.BRERxStop | \
+ hcec->Init.BREErrorBitGen | hcec->Init.LBPEErrorBitGen | hcec->Init.BroadcastMsgNoErrorBitGen | \
+ hcec->Init.SignalFreeTimeOption | ((uint32_t)(hcec->Init.OwnAddress) << 16U) | \
+ hcec->Init.ListenMode;
+
+ /* Enable the following CEC Transmission/Reception interrupts as
+ * well as the following CEC Transmission/Reception Errors interrupts
+ * Rx Byte Received IT
+ * End of Reception IT
+ * Rx overrun
+ * Rx bit rising error
+ * Rx short bit period error
+ * Rx long bit period error
+ * Rx missing acknowledge
+ * Tx Byte Request IT
+ * End of Transmission IT
+ * Tx Missing Acknowledge IT
+ * Tx-Error IT
+ * Tx-Buffer Underrun IT
+ * Tx arbitration lost */
+ __HAL_CEC_ENABLE_IT(hcec, CEC_IT_RXBR | CEC_IT_RXEND | CEC_IER_RX_ALL_ERR | CEC_IT_TXBR | CEC_IT_TXEND |
+ CEC_IER_TX_ALL_ERR);
+
+ /* Enable the CEC Peripheral */
+ __HAL_CEC_ENABLE(hcec);
+
+ hcec->ErrorCode = HAL_CEC_ERROR_NONE;
+ hcec->gState = HAL_CEC_STATE_READY;
+ hcec->RxState = HAL_CEC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the CEC peripheral
+ * @param hcec CEC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CEC_DeInit(CEC_HandleTypeDef *hcec)
+{
+ /* Check the CEC handle allocation */
+ if (hcec == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
+
+ hcec->gState = HAL_CEC_STATE_BUSY;
+
+#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
+ if (hcec->MspDeInitCallback == NULL)
+ {
+ hcec->MspDeInitCallback = HAL_CEC_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware */
+ hcec->MspDeInitCallback(hcec);
+
+#else
+ /* DeInit the low level hardware */
+ HAL_CEC_MspDeInit(hcec);
+#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
+
+ /* Disable the Peripheral */
+ __HAL_CEC_DISABLE(hcec);
+
+ /* Clear Flags */
+ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXEND | CEC_FLAG_TXBR | CEC_FLAG_RXBR | CEC_FLAG_RXEND | CEC_ISR_ALL_ERROR);
+
+ /* Disable the following CEC Transmission/Reception interrupts as
+ * well as the following CEC Transmission/Reception Errors interrupts
+ * Rx Byte Received IT
+ * End of Reception IT
+ * Rx overrun
+ * Rx bit rising error
+ * Rx short bit period error
+ * Rx long bit period error
+ * Rx missing acknowledge
+ * Tx Byte Request IT
+ * End of Transmission IT
+ * Tx Missing Acknowledge IT
+ * Tx-Error IT
+ * Tx-Buffer Underrun IT
+ * Tx arbitration lost */
+ __HAL_CEC_DISABLE_IT(hcec, CEC_IT_RXBR | CEC_IT_RXEND | CEC_IER_RX_ALL_ERR | CEC_IT_TXBR | CEC_IT_TXEND |
+ CEC_IER_TX_ALL_ERR);
+
+ hcec->ErrorCode = HAL_CEC_ERROR_NONE;
+ hcec->gState = HAL_CEC_STATE_RESET;
+ hcec->RxState = HAL_CEC_STATE_RESET;
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hcec);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the Own Address of the CEC device
+ * @param hcec CEC handle
+ * @param CEC_OwnAddress The CEC own address.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CEC_SetDeviceAddress(CEC_HandleTypeDef *hcec, uint16_t CEC_OwnAddress)
+{
+ /* Check the parameters */
+ assert_param(IS_CEC_OWN_ADDRESS(CEC_OwnAddress));
+
+ if ((hcec->gState == HAL_CEC_STATE_READY) && (hcec->RxState == HAL_CEC_STATE_READY))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hcec);
+
+ hcec->gState = HAL_CEC_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_CEC_DISABLE(hcec);
+
+ if (CEC_OwnAddress != CEC_OWN_ADDRESS_NONE)
+ {
+ hcec->Instance->CFGR |= ((uint32_t)CEC_OwnAddress << 16);
+ }
+ else
+ {
+ hcec->Instance->CFGR &= ~(CEC_CFGR_OAR);
+ }
+
+ hcec->gState = HAL_CEC_STATE_READY;
+ hcec->ErrorCode = HAL_CEC_ERROR_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcec);
+
+ /* Enable the Peripheral */
+ __HAL_CEC_ENABLE(hcec);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief CEC MSP Init
+ * @param hcec CEC handle
+ * @retval None
+ */
+__weak void HAL_CEC_MspInit(CEC_HandleTypeDef *hcec)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcec);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CEC_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief CEC MSP DeInit
+ * @param hcec CEC handle
+ * @retval None
+ */
+__weak void HAL_CEC_MspDeInit(CEC_HandleTypeDef *hcec)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcec);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CEC_MspDeInit can be implemented in the user file
+ */
+}
+#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User CEC Callback
+ * To be used instead of the weak predefined callback
+ * @param hcec CEC handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
+ * @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CEC_RegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID,
+ pCEC_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hcec);
+
+ if (hcec->gState == HAL_CEC_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_CEC_TX_CPLT_CB_ID :
+ hcec->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_CEC_ERROR_CB_ID :
+ hcec->ErrorCallback = pCallback;
+ break;
+
+ case HAL_CEC_MSPINIT_CB_ID :
+ hcec->MspInitCallback = pCallback;
+ break;
+
+ case HAL_CEC_MSPDEINIT_CB_ID :
+ hcec->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hcec->gState == HAL_CEC_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_CEC_MSPINIT_CB_ID :
+ hcec->MspInitCallback = pCallback;
+ break;
+
+ case HAL_CEC_MSPDEINIT_CB_ID :
+ hcec->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hcec);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an CEC Callback
+ * CEC callabck is redirected to the weak predefined callback
+ * @param hcec uart handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
+ * @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_CEC_UnRegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hcec);
+
+ if (hcec->gState == HAL_CEC_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_CEC_TX_CPLT_CB_ID :
+ hcec->TxCpltCallback = HAL_CEC_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ break;
+
+ case HAL_CEC_ERROR_CB_ID :
+ hcec->ErrorCallback = HAL_CEC_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_CEC_MSPINIT_CB_ID :
+ hcec->MspInitCallback = HAL_CEC_MspInit;
+ break;
+
+ case HAL_CEC_MSPDEINIT_CB_ID :
+ hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hcec->gState == HAL_CEC_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_CEC_MSPINIT_CB_ID :
+ hcec->MspInitCallback = HAL_CEC_MspInit;
+ break;
+
+ case HAL_CEC_MSPDEINIT_CB_ID :
+ hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hcec);
+
+ return status;
+}
+
+/**
+ * @brief Register CEC RX complete Callback
+ * To be used instead of the weak HAL_CEC_RxCpltCallback() predefined callback
+ * @param hcec CEC handle
+ * @param pCallback pointer to the Rx transfer compelete Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CEC_RegisterRxCpltCallback(CEC_HandleTypeDef *hcec, pCEC_RxCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hcec);
+
+ if (HAL_CEC_STATE_READY == hcec->RxState)
+ {
+ hcec->RxCpltCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hcec);
+ return status;
+}
+
+/**
+ * @brief UnRegister CEC RX complete Callback
+ * CEC RX complete Callback is redirected to the weak HAL_CEC_RxCpltCallback() predefined callback
+ * @param hcec CEC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CEC_UnRegisterRxCpltCallback(CEC_HandleTypeDef *hcec)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hcec);
+
+ if (HAL_CEC_STATE_READY == hcec->RxState)
+ {
+ hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak CEC RxCpltCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hcec);
+ return status;
+}
+#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup CEC_Exported_Functions_Group2 Input and Output operation functions
+ * @brief CEC Transmit/Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ This subsection provides a set of functions allowing to manage the CEC data transfers.
+
+ (#) The CEC handle must contain the initiator (TX side) and the destination (RX side)
+ logical addresses (4-bit long addresses, 0xF for broadcast messages destination)
+
+ (#) The communication is performed using Interrupts.
+ These API's return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated CEC IRQ when using Interrupt mode.
+ The HAL_CEC_TxCpltCallback(), HAL_CEC_RxCpltCallback() user callbacks
+ will be executed respectively at the end of the transmit or Receive process
+ The HAL_CEC_ErrorCallback() user callback will be executed when a communication
+ error is detected
+
+ (#) API's with Interrupt are :
+ (+) HAL_CEC_Transmit_IT()
+ (+) HAL_CEC_IRQHandler()
+
+ (#) A set of User Callbacks are provided:
+ (+) HAL_CEC_TxCpltCallback()
+ (+) HAL_CEC_RxCpltCallback()
+ (+) HAL_CEC_ErrorCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Send data in interrupt mode
+ * @param hcec CEC handle
+ * @param InitiatorAddress Initiator address
+ * @param DestinationAddress destination logical address
+ * @param pData pointer to input byte data buffer
+ * @param Size amount of data to be sent in bytes (without counting the header).
+ * 0 means only the header is sent (ping operation).
+ * Maximum TX size is 15 bytes (1 opcode and up to 14 operands).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t DestinationAddress,
+ uint8_t *pData, uint32_t Size)
+{
+ /* if the IP isn't already busy and if there is no previous transmission
+ already pending due to arbitration lost */
+ if (hcec->gState == HAL_CEC_STATE_READY)
+ {
+ if ((pData == NULL) && (Size > 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ assert_param(IS_CEC_ADDRESS(DestinationAddress));
+ assert_param(IS_CEC_ADDRESS(InitiatorAddress));
+ assert_param(IS_CEC_MSGSIZE(Size));
+
+ /* Process Locked */
+ __HAL_LOCK(hcec);
+ hcec->pTxBuffPtr = pData;
+ hcec->gState = HAL_CEC_STATE_BUSY_TX;
+ hcec->ErrorCode = HAL_CEC_ERROR_NONE;
+
+ /* initialize the number of bytes to send,
+ * 0 means only one header is sent (ping operation) */
+ hcec->TxXferCount = (uint16_t)Size;
+
+ /* in case of no payload (Size = 0), sender is only pinging the system;
+ Set TX End of Message (TXEOM) bit, must be set before writing data to TXDR */
+ if (Size == 0U)
+ {
+ __HAL_CEC_LAST_BYTE_TX_SET(hcec);
+ }
+
+ /* send header block */
+ hcec->Instance->TXDR = (uint32_t)(((uint32_t)InitiatorAddress << CEC_INITIATOR_LSB_POS) | DestinationAddress);
+
+ /* Set TX Start of Message (TXSOM) bit */
+ __HAL_CEC_FIRST_BYTE_TX_SET(hcec);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcec);
+
+ return HAL_OK;
+
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Get size of the received frame.
+ * @param hcec CEC handle
+ * @retval Frame size
+ */
+uint32_t HAL_CEC_GetLastReceivedFrameSize(CEC_HandleTypeDef *hcec)
+{
+ return hcec->RxXferSize;
+}
+
+/**
+ * @brief Change Rx Buffer.
+ * @param hcec CEC handle
+ * @param Rxbuffer Rx Buffer
+ * @note This function can be called only inside the HAL_CEC_RxCpltCallback()
+ * @retval Frame size
+ */
+void HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef *hcec, uint8_t *Rxbuffer)
+{
+ hcec->Init.RxBuffer = Rxbuffer;
+}
+
+/**
+ * @brief This function handles CEC interrupt requests.
+ * @param hcec CEC handle
+ * @retval None
+ */
+void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
+{
+
+ /* save interrupts register for further error or interrupts handling purposes */
+ uint32_t reg;
+ reg = hcec->Instance->ISR;
+
+
+ /* ----------------------------Arbitration Lost Management----------------------------------*/
+ /* CEC TX arbitration error interrupt occurred --------------------------------------*/
+ if ((reg & CEC_FLAG_ARBLST) != 0U)
+ {
+ hcec->ErrorCode = HAL_CEC_ERROR_ARBLST;
+ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_ARBLST);
+ }
+
+ /* ----------------------------Rx Management----------------------------------*/
+ /* CEC RX byte received interrupt ---------------------------------------------------*/
+ if ((reg & CEC_FLAG_RXBR) != 0U)
+ {
+ /* reception is starting */
+ hcec->RxState = HAL_CEC_STATE_BUSY_RX;
+ hcec->RxXferSize++;
+ /* read received byte */
+ *hcec->Init.RxBuffer = (uint8_t) hcec->Instance->RXDR;
+ hcec->Init.RxBuffer++;
+ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXBR);
+ }
+
+ /* CEC RX end received interrupt ---------------------------------------------------*/
+ if ((reg & CEC_FLAG_RXEND) != 0U)
+ {
+ /* clear IT */
+ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXEND);
+
+ /* Rx process is completed, restore hcec->RxState to Ready */
+ hcec->RxState = HAL_CEC_STATE_READY;
+ hcec->ErrorCode = HAL_CEC_ERROR_NONE;
+ hcec->Init.RxBuffer -= hcec->RxXferSize;
+#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1U)
+ hcec->RxCpltCallback(hcec, hcec->RxXferSize);
+#else
+ HAL_CEC_RxCpltCallback(hcec, hcec->RxXferSize);
+#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
+ hcec->RxXferSize = 0U;
+ }
+
+ /* ----------------------------Tx Management----------------------------------*/
+ /* CEC TX byte request interrupt ------------------------------------------------*/
+ if ((reg & CEC_FLAG_TXBR) != 0U)
+ {
+ if (hcec->TxXferCount == 0U)
+ {
+ /* if this is the last byte transmission, set TX End of Message (TXEOM) bit */
+ __HAL_CEC_LAST_BYTE_TX_SET(hcec);
+ hcec->Instance->TXDR = *hcec->pTxBuffPtr;
+ hcec->pTxBuffPtr++;
+ }
+ else
+ {
+ hcec->Instance->TXDR = *hcec->pTxBuffPtr;
+ hcec->pTxBuffPtr++;
+ hcec->TxXferCount--;
+ }
+ /* clear Tx-Byte request flag */
+ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXBR);
+ }
+
+ /* CEC TX end interrupt ------------------------------------------------*/
+ if ((reg & CEC_FLAG_TXEND) != 0U)
+ {
+ __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXEND);
+
+ /* Tx process is ended, restore hcec->gState to Ready */
+ hcec->gState = HAL_CEC_STATE_READY;
+ /* Call the Process Unlocked before calling the Tx call back API to give the possibility to
+ start again the Transmission under the Tx call back API */
+ __HAL_UNLOCK(hcec);
+ hcec->ErrorCode = HAL_CEC_ERROR_NONE;
+#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1U)
+ hcec->TxCpltCallback(hcec);
+#else
+ HAL_CEC_TxCpltCallback(hcec);
+#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
+ }
+
+ /* ----------------------------Rx/Tx Error Management----------------------------------*/
+ if ((reg & (CEC_ISR_RXOVR | CEC_ISR_BRE | CEC_ISR_SBPE | CEC_ISR_LBPE | CEC_ISR_RXACKE | CEC_ISR_TXUDR | CEC_ISR_TXERR |
+ CEC_ISR_TXACKE)) != 0U)
+ {
+ hcec->ErrorCode = reg;
+ __HAL_CEC_CLEAR_FLAG(hcec, HAL_CEC_ERROR_RXOVR | HAL_CEC_ERROR_BRE | CEC_FLAG_LBPE | CEC_FLAG_SBPE |
+ HAL_CEC_ERROR_RXACKE | HAL_CEC_ERROR_TXUDR | HAL_CEC_ERROR_TXERR | HAL_CEC_ERROR_TXACKE);
+
+
+ if ((reg & (CEC_ISR_RXOVR | CEC_ISR_BRE | CEC_ISR_SBPE | CEC_ISR_LBPE | CEC_ISR_RXACKE)) != 0U)
+ {
+ hcec->Init.RxBuffer -= hcec->RxXferSize;
+ hcec->RxXferSize = 0U;
+ hcec->RxState = HAL_CEC_STATE_READY;
+ }
+ else if (((reg & CEC_ISR_ARBLST) == 0U) && ((reg & (CEC_ISR_TXUDR | CEC_ISR_TXERR | CEC_ISR_TXACKE)) != 0U))
+ {
+ /* Set the CEC state ready to be able to start again the process */
+ hcec->gState = HAL_CEC_STATE_READY;
+ }
+ else
+ {
+ /* Nothing todo*/
+ }
+#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1U)
+ hcec->ErrorCallback(hcec);
+#else
+ /* Error Call Back */
+ HAL_CEC_ErrorCallback(hcec);
+#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing todo*/
+ }
+}
+
+/**
+ * @brief Tx Transfer completed callback
+ * @param hcec CEC handle
+ * @retval None
+ */
+__weak void HAL_CEC_TxCpltCallback(CEC_HandleTypeDef *hcec)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcec);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CEC_TxCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback
+ * @param hcec CEC handle
+ * @param RxFrameSize Size of frame
+ * @retval None
+ */
+__weak void HAL_CEC_RxCpltCallback(CEC_HandleTypeDef *hcec, uint32_t RxFrameSize)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcec);
+ UNUSED(RxFrameSize);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CEC_RxCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief CEC error callbacks
+ * @param hcec CEC handle
+ * @retval None
+ */
+__weak void HAL_CEC_ErrorCallback(CEC_HandleTypeDef *hcec)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcec);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CEC_ErrorCallback can be implemented in the user file
+ */
+}
+/**
+ * @}
+ */
+
+/** @defgroup CEC_Exported_Functions_Group3 Peripheral Control function
+ * @brief CEC control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control function #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the CEC.
+ (+) HAL_CEC_GetState() API can be helpful to check in run-time the state of the CEC peripheral.
+ (+) HAL_CEC_GetError() API can be helpful to check in run-time the error of the CEC peripheral.
+@endverbatim
+ * @{
+ */
+/**
+ * @brief return the CEC state
+ * @param hcec pointer to a CEC_HandleTypeDef structure that contains
+ * the configuration information for the specified CEC module.
+ * @retval HAL state
+ */
+HAL_CEC_StateTypeDef HAL_CEC_GetState(CEC_HandleTypeDef *hcec)
+{
+ uint32_t temp1, temp2;
+ temp1 = hcec->gState;
+ temp2 = hcec->RxState;
+
+ return (HAL_CEC_StateTypeDef)(temp1 | temp2);
+}
+
+/**
+ * @brief Return the CEC error code
+ * @param hcec pointer to a CEC_HandleTypeDef structure that contains
+ * the configuration information for the specified CEC.
+ * @retval CEC Error Code
+ */
+uint32_t HAL_CEC_GetError(CEC_HandleTypeDef *hcec)
+{
+ return hcec->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+#endif /* CEC */
+#endif /* HAL_CEC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_comp.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_comp.c
new file mode 100644
index 0000000000..8033926129
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_comp.c
@@ -0,0 +1,1250 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_comp.c
+ * @author MCD Application Team
+ * @brief COMP HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the COMP peripheral:
+ * + Initialization and de-initialization functions
+ * + Start/Stop operation functions in polling mode
+ * + Start/Stop operation functions in interrupt mode
+ * + Peripheral control functions
+ * + Peripheral state functions
+ @verbatim
+ ================================================================================
+ ##### COMP Peripheral features #####
+ ================================================================================
+
+ [..]
+ The STM32H7xx device family integrates two analog comparators instances
+ COMP1 and COMP2:
+ (#) The COMP input minus (inverting input) and input plus (non inverting input)
+ can be set to internal references or to GPIO pins
+ (refer to GPIO list in reference manual).
+
+ (#) The COMP output level is available using HAL_COMP_GetOutputLevel()
+ and can be redirected to other peripherals: GPIO pins (in mode
+ alternate functions for comparator), timers.
+ (refer to GPIO list in reference manual).
+
+ (#) Pairs of comparators instances can be combined in window mode
+ (2 consecutive instances odd and even COMP<x> and COMP<x+1>).
+
+ (#) The comparators have interrupt capability through the EXTI controller
+ with wake-up from sleep and stop modes:
+ (++) COMP1 is internally connected to EXTI Line 20
+ (++) COMP2 is internally connected to EXTI Line 21
+
+ [..]
+ From the corresponding IRQ handler, the right interrupt source can be retrieved
+ using macro __HAL_COMP_COMP1_EXTI_GET_FLAG() and __HAL_COMP_COMP2_EXTI_GET_FLAG().
+
+
+
+ ##### How to use this driver #####
+ ================================================================================
+ [..]
+ This driver provides functions to configure and program the comparator instances of
+ STM32H7xx devices.
+
+ To use the comparator, perform the following steps:
+
+ (#) Initialize the COMP low level resources by implementing the HAL_COMP_MspInit():
+ (++) Configure the GPIO connected to comparator inputs plus and minus in analog mode
+ using HAL_GPIO_Init().
+ (++) If needed, configure the GPIO connected to comparator output in alternate function mode
+ using HAL_GPIO_Init().
+ (++) If required enable the COMP interrupt by configuring and enabling EXTI line in Interrupt mode and
+ selecting the desired sensitivity level using HAL_GPIO_Init() function. After that enable the comparator
+ interrupt vector using HAL_NVIC_EnableIRQ() function.
+
+ (#) Configure the comparator using HAL_COMP_Init() function:
+ (++) Select the input minus (inverting input)
+ (++) Select the input plus (non-inverting input)
+ (++) Select the hysteresis
+ (++) Select the blanking source
+ (++) Select the output polarity
+ (++) Select the power mode
+ (++) Select the window mode
+ -@@- HAL_COMP_Init() calls internally __HAL_RCC_SYSCFG_CLK_ENABLE()
+ to enable internal control clock of the comparators.
+ However, this is a legacy strategy.
+ Therefore, for compatibility anticipation, it is recommended to
+ implement __HAL_RCC_SYSCFG_CLK_ENABLE() in "HAL_COMP_MspInit()".
+ In STM32H7,COMP clock enable __HAL_RCC_COMP12_CLK_ENABLE() must
+ be implemented by user in "HAL_COMP_MspInit()".
+ (#) Reconfiguration on-the-fly of comparator can be done by calling again
+ function HAL_COMP_Init() with new input structure parameters values.
+
+ (#) Enable the comparator using HAL_COMP_Start() or HAL_COMP_Start_IT()to be enabled
+ with the interrupt through NVIC of the CPU.
+ Note: HAL_COMP_Start_IT() must be called after each interrupt otherwise the interrupt
+ mode will stay disabled.
+
+ (#) Use HAL_COMP_GetOutputLevel() or HAL_COMP_TriggerCallback()
+ functions to manage comparator outputs(output level or events)
+
+ (#) Disable the comparator using HAL_COMP_Stop() or HAL_COMP_Stop_IT()
+ to disable the interrupt too.
+
+ (#) De-initialize the comparator using HAL_COMP_DeInit() function.
+
+ (#) For safety purpose, comparator configuration can be locked using HAL_COMP_Lock() function.
+ The only way to unlock the comparator is a device hardware reset.
+
+ *** Callback registration ***
+ =============================================
+ [..]
+
+ The compilation flag USE_HAL_COMP_REGISTER_CALLBACKS, when set to 1,
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions @ref HAL_COMP_RegisterCallback()
+ to register an interrupt callback.
+ [..]
+
+ Function @ref HAL_COMP_RegisterCallback() allows to register following callbacks:
+ (+) TriggerCallback : callback for COMP trigger.
+ (+) 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.
+ [..]
+
+ Use function @ref HAL_COMP_UnRegisterCallback to reset a callback to the default
+ weak function.
+ [..]
+
+ @ref HAL_COMP_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TriggerCallback : callback for COMP trigger.
+ (+) MspInitCallback : callback for Msp Init.
+ (+) MspDeInitCallback : callback for Msp DeInit.
+ [..]
+
+ By default, after the @ref HAL_COMP_Init() and when the state is @ref HAL_COMP_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ example @ref HAL_COMP_TriggerCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the @ref HAL_COMP_Init()/ @ref HAL_COMP_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ [..]
+
+ If MspInit or MspDeInit are not null, the @ref HAL_COMP_Init()/ @ref HAL_COMP_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+ [..]
+
+ Callbacks can be registered/unregistered in @ref HAL_COMP_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in @ref HAL_COMP_STATE_READY or @ref HAL_COMP_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 @ref HAL_COMP_RegisterCallback() before calling @ref HAL_COMP_DeInit()
+ or @ref HAL_COMP_Init() function.
+ [..]
+
+ When the compilation flag USE_HAL_COMP_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
+ ******************************************************************************
+
+ Table 1. COMP inputs and output for STM32H7xx devices
+ +---------------------------------------------------------+
+ | | | COMP1 | COMP2 |
+ |----------------|----------------|-----------|-----------|
+ | | IO1 | PB0 | PE9 |
+ | Input plus | IO2 | PB2 | PE11 |
+ | | | | |
+ |----------------|----------------|-----------------------|
+ | | 1/4 VrefInt | Available | Available |
+ | | 1/2 VrefInt | Available | Available |
+ | | 3/4 VrefInt | Available | Available |
+ | Input minus | VrefInt | Available | Available |
+ | | DAC1 channel 1 | Available | Available |
+ | | DAC1 channel 2 | Available | Available |
+ | | IO1 | PB1 | PE10 |
+ | | IO2 | PC4 | PE7 |
+ | | | | |
+ | | | | |
+ | | | | |
+ +---------------------------------------------------------+
+ | Output | | PC5 (1) | PE8 (1) |
+ | | | PE12 (1) | PE13 (1) |
+ | | | TIM (2) | TIM (2) |
+ +---------------------------------------------------------+
+ (1) GPIO must be set to alternate function for comparator
+ (2) Comparators output to timers is set in timers instances.
+
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup COMP COMP
+ * @brief COMP HAL module driver
+ * @{
+ */
+
+#ifdef HAL_COMP_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup COMP_Private_Constants
+ * @{
+ */
+
+/* Delay for COMP startup time. */
+/* Note: Delay required to reach propagation delay specification. */
+/* Literal set to maximum value (refer to device datasheet, */
+/* parameter "tSTART"). */
+/* Unit: us */
+#define COMP_DELAY_STARTUP_US (80UL) /*!< Delay for COMP startup time */
+
+/* Delay for COMP voltage scaler stabilization time. */
+/* Literal set to maximum value (refer to device datasheet, */
+/* parameter "tSTART_SCALER"). */
+/* Unit: us */
+#define COMP_DELAY_VOLTAGE_SCALER_STAB_US (200UL) /*!< Delay for COMP voltage scaler stabilization time */
+
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup COMP_Exported_Functions COMP Exported Functions
+ * @{
+ */
+
+/** @defgroup COMP_Exported_Functions_Group1 Initialization/de-initialization functions
+ * @brief Initialization and de-initialization functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions to initialize and de-initialize comparators
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the COMP according to the specified
+ * parameters in the COMP_InitTypeDef and initialize the associated handle.
+ * @note If the selected comparator is locked, initialization can't be performed.
+ * To unlock the configuration, perform a system reset.
+ * @param hcomp COMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_COMP_Init(COMP_HandleTypeDef *hcomp)
+{
+ uint32_t tmp_csr ;
+ uint32_t exti_line ;
+ uint32_t comp_voltage_scaler_initialized; /* Value "0" is comparator voltage scaler is not initialized */
+ __IO uint32_t wait_loop_index = 0UL;
+
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the COMP handle allocation and lock status */
+ if(hcomp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(__HAL_COMP_IS_LOCKED(hcomp))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
+ assert_param(IS_COMP_INPUT_PLUS(hcomp->Instance, hcomp->Init.NonInvertingInput));
+ assert_param(IS_COMP_INPUT_MINUS(hcomp->Instance, hcomp->Init.InvertingInput));
+ assert_param(IS_COMP_OUTPUTPOL(hcomp->Init.OutputPol));
+ assert_param(IS_COMP_POWERMODE(hcomp->Init.Mode));
+ assert_param(IS_COMP_HYSTERESIS(hcomp->Init.Hysteresis));
+ assert_param(IS_COMP_BLANKINGSRCE(hcomp->Init.BlankingSrce));
+ assert_param(IS_COMP_TRIGGERMODE(hcomp->Init.TriggerMode));
+ assert_param(IS_COMP_WINDOWMODE(hcomp->Init.WindowMode));
+
+ if(hcomp->State == HAL_COMP_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hcomp->Lock = HAL_UNLOCKED;
+
+ /* Set COMP error code to none */
+ COMP_CLEAR_ERRORCODE(hcomp);
+
+#if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
+ /* Init the COMP Callback settings */
+ hcomp->TriggerCallback = HAL_COMP_TriggerCallback; /* Legacy weak callback */
+
+ if (hcomp->MspInitCallback == NULL)
+ {
+ hcomp->MspInitCallback = HAL_COMP_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware */
+ hcomp->MspInitCallback(hcomp);
+#else
+ /* Init the low level hardware */
+ HAL_COMP_MspInit(hcomp);
+#endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
+ }
+ /* Memorize voltage scaler state before initialization */
+ comp_voltage_scaler_initialized = READ_BIT(hcomp->Instance->CFGR, COMP_CFGRx_SCALEN);
+
+ /* Set COMP parameters */
+ /* Set INMSEL bits according to hcomp->Init.InvertingInput value */
+ /* Set INPSEL bits according to hcomp->Init.NonInvertingInput value */
+ /* Set BLANKING bits according to hcomp->Init.BlankingSrce value */
+ /* Set HYST bits according to hcomp->Init.Hysteresis value */
+ /* Set POLARITY bit according to hcomp->Init.OutputPol value */
+ /* Set POWERMODE bits according to hcomp->Init.Mode value */
+
+ tmp_csr = (hcomp->Init.InvertingInput | \
+ hcomp->Init.NonInvertingInput | \
+ hcomp->Init.BlankingSrce | \
+ hcomp->Init.Hysteresis | \
+ hcomp->Init.OutputPol | \
+ hcomp->Init.Mode );
+
+ /* Set parameters in COMP register */
+ /* Note: Update all bits except read-only, lock and enable bits */
+#if defined (COMP_CFGRx_INP2SEL)
+ MODIFY_REG(hcomp->Instance->CFGR,
+ COMP_CFGRx_PWRMODE | COMP_CFGRx_INMSEL | COMP_CFGRx_INPSEL |
+ COMP_CFGRx_INP2SEL | COMP_CFGRx_WINMODE | COMP_CFGRx_POLARITY | COMP_CFGRx_HYST |
+ COMP_CFGRx_BLANKING | COMP_CFGRx_BRGEN | COMP_CFGRx_SCALEN,
+ tmp_csr
+ );
+#else
+ MODIFY_REG(hcomp->Instance->CFGR,
+ COMP_CFGRx_PWRMODE | COMP_CFGRx_INMSEL | COMP_CFGRx_INPSEL |
+ COMP_CFGRx_WINMODE | COMP_CFGRx_POLARITY | COMP_CFGRx_HYST |
+ COMP_CFGRx_BLANKING | COMP_CFGRx_BRGEN | COMP_CFGRx_SCALEN,
+ tmp_csr
+ );
+#endif
+ /* Set window mode */
+ /* Note: Window mode bit is located into 1 out of the 2 pairs of COMP */
+ /* instances. Therefore, this function can update another COMP */
+ /* instance that the one currently selected. */
+ if(hcomp->Init.WindowMode == COMP_WINDOWMODE_COMP1_INPUT_PLUS_COMMON)
+ {
+ SET_BIT(hcomp->Instance->CFGR, COMP_CFGRx_WINMODE);
+ }
+ else
+ {
+ CLEAR_BIT(hcomp->Instance->CFGR, COMP_CFGRx_WINMODE);
+ }
+ /* Delay for COMP scaler bridge voltage stabilization */
+ /* Apply the delay if voltage scaler bridge is enabled for the first time */
+ if ((READ_BIT(hcomp->Instance->CFGR, COMP_CFGRx_SCALEN) != 0UL) &&
+ (comp_voltage_scaler_initialized != 0UL) )
+ {
+ /* Wait loop initialization and execution */
+ /* Note: Variable divided by 2 to compensate partially */
+ /* CPU processing cycles.*/
+
+ wait_loop_index = (COMP_DELAY_VOLTAGE_SCALER_STAB_US * (SystemCoreClock / (1000000UL * 2UL)));
+
+ while(wait_loop_index != 0UL)
+ {
+ wait_loop_index --;
+ }
+ }
+
+ /* Get the EXTI line corresponding to the selected COMP instance */
+ exti_line = COMP_GET_EXTI_LINE(hcomp->Instance);
+
+ /* Manage EXTI settings */
+ if((hcomp->Init.TriggerMode & (COMP_EXTI_IT | COMP_EXTI_EVENT)) != 0UL)
+ {
+ /* Configure EXTI rising edge */
+ if((hcomp->Init.TriggerMode & COMP_EXTI_RISING) != 0UL)
+ {
+ SET_BIT(EXTI->RTSR1, exti_line);
+ }
+ else
+ {
+ CLEAR_BIT(EXTI->RTSR1, exti_line);
+ }
+
+ /* Configure EXTI falling edge */
+ if((hcomp->Init.TriggerMode & COMP_EXTI_FALLING) != 0UL)
+ {
+ SET_BIT(EXTI->FTSR1, exti_line);
+ }
+ else
+ {
+ CLEAR_BIT(EXTI->FTSR1, exti_line);
+ }
+
+#if !defined (CORE_CM4)
+ /* Clear COMP EXTI pending bit (if any) */
+ WRITE_REG(EXTI->PR1, exti_line);
+
+ /* Configure EXTI event mode */
+ if((hcomp->Init.TriggerMode & COMP_EXTI_EVENT) != 0UL)
+ {
+ SET_BIT(EXTI->EMR1, exti_line);
+ }
+ else
+ {
+ CLEAR_BIT(EXTI->EMR1, exti_line);
+ }
+
+ /* Configure EXTI interrupt mode */
+ if((hcomp->Init.TriggerMode & COMP_EXTI_IT) != 0UL)
+ {
+ SET_BIT(EXTI->IMR1, exti_line);
+ }
+ else
+ {
+ CLEAR_BIT(EXTI->IMR1, exti_line);
+ }
+ }
+ else
+ {
+ /* Disable EXTI event mode */
+ CLEAR_BIT(EXTI->EMR1, exti_line);
+
+ /* Disable EXTI interrupt mode */
+ CLEAR_BIT(EXTI->IMR1, exti_line);
+ }
+#else
+ /* Clear COMP EXTI pending bit (if any) */
+ WRITE_REG(EXTI->C2PR1, exti_line);
+
+ /* Configure EXTI event mode */
+ if((hcomp->Init.TriggerMode & COMP_EXTI_EVENT) != 0UL)
+ {
+ SET_BIT(EXTI->C2EMR1, exti_line);
+ }
+ else
+ {
+ CLEAR_BIT(EXTI->C2EMR1, exti_line);
+ }
+
+ /* Configure EXTI interrupt mode */
+ if((hcomp->Init.TriggerMode & COMP_EXTI_IT) != 0UL)
+ {
+ SET_BIT(EXTI->C2IMR1, exti_line);
+ }
+ else
+ {
+ CLEAR_BIT(EXTI->C2IMR1, exti_line);
+ }
+ }
+ else
+ {
+ /* Disable EXTI event mode */
+ CLEAR_BIT(EXTI->C2EMR1, exti_line);
+
+ /* Disable EXTI interrupt mode */
+ CLEAR_BIT(EXTI->C2IMR1, exti_line);
+ }
+#endif
+ /* Set HAL COMP handle state */
+ /* Note: Transition from state reset to state ready, */
+ /* otherwise (coming from state ready or busy) no state update. */
+ if (hcomp->State == HAL_COMP_STATE_RESET)
+ {
+
+ hcomp->State = HAL_COMP_STATE_READY;
+ }
+
+ }
+
+ return status;
+}
+
+/**
+ * @brief DeInitialize the COMP peripheral.
+ * @note Deinitialization cannot be performed if the COMP configuration is locked.
+ * To unlock the configuration, perform a system reset.
+ * @param hcomp COMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_COMP_DeInit(COMP_HandleTypeDef *hcomp)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the COMP handle allocation and lock status */
+ if(hcomp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(__HAL_COMP_IS_LOCKED(hcomp))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
+
+ /* Set COMP_CFGR register to reset value */
+ WRITE_REG(hcomp->Instance->CFGR, 0x00000000UL);
+
+#if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
+ if (hcomp->MspDeInitCallback == NULL)
+ {
+ hcomp->MspDeInitCallback = HAL_COMP_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware */
+ hcomp->MspDeInitCallback(hcomp);
+#else
+ /* DeInit the low level hardware */
+ HAL_COMP_MspDeInit(hcomp);
+#endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
+
+ /* Set HAL COMP handle state */
+ hcomp->State = HAL_COMP_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hcomp);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Initialize the COMP MSP.
+ * @param hcomp COMP handle
+ * @retval None
+ */
+__weak void HAL_COMP_MspInit(COMP_HandleTypeDef *hcomp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcomp);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_COMP_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the COMP MSP.
+ * @param hcomp COMP handle
+ * @retval None
+ */
+__weak void HAL_COMP_MspDeInit(COMP_HandleTypeDef *hcomp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcomp);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_COMP_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User COMP Callback
+ * To be used instead of the weak predefined callback
+ * @param hcomp Pointer to a COMP_HandleTypeDef structure that contains
+ * the configuration information for the specified COMP.
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_COMP_TRIGGER_CB_ID Trigger callback ID
+ * @arg @ref HAL_COMP_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_COMP_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_COMP_RegisterCallback(COMP_HandleTypeDef *hcomp, HAL_COMP_CallbackIDTypeDef CallbackID, pCOMP_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ if (HAL_COMP_STATE_READY == hcomp->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_COMP_TRIGGER_CB_ID :
+ hcomp->TriggerCallback = pCallback;
+ break;
+
+ case HAL_COMP_MSPINIT_CB_ID :
+ hcomp->MspInitCallback = pCallback;
+ break;
+
+ case HAL_COMP_MSPDEINIT_CB_ID :
+ hcomp->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_COMP_STATE_RESET == hcomp->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_COMP_MSPINIT_CB_ID :
+ hcomp->MspInitCallback = pCallback;
+ break;
+
+ case HAL_COMP_MSPDEINIT_CB_ID :
+ hcomp->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a COMP Callback
+ * COMP callback is redirected to the weak predefined callback
+ * @param hcomp Pointer to a COMP_HandleTypeDef structure that contains
+ * the configuration information for the specified COMP.
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_COMP_TRIGGER_CB_ID Trigger callback ID
+ * @arg @ref HAL_COMP_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_COMP_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_COMP_UnRegisterCallback(COMP_HandleTypeDef *hcomp, HAL_COMP_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (HAL_COMP_STATE_READY == hcomp->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_COMP_TRIGGER_CB_ID :
+ hcomp->TriggerCallback = HAL_COMP_TriggerCallback; /* Legacy weak callback */
+ break;
+
+ case HAL_COMP_MSPINIT_CB_ID :
+ hcomp->MspInitCallback = HAL_COMP_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_COMP_MSPDEINIT_CB_ID :
+ hcomp->MspDeInitCallback = HAL_COMP_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_COMP_STATE_RESET == hcomp->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_COMP_MSPINIT_CB_ID :
+ hcomp->MspInitCallback = HAL_COMP_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_COMP_MSPDEINIT_CB_ID :
+ hcomp->MspDeInitCallback = HAL_COMP_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hcomp->ErrorCode |= HAL_COMP_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+#endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Exported_Functions_Group2 Start-Stop operation functions
+ * @brief Start-Stop operation functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start a Comparator instance without interrupt.
+ (+) Stop a Comparator instance without interrupt.
+ (+) Start a Comparator instance with interrupt generation.
+ (+) Stop a Comparator instance with interrupt generation.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the comparator.
+ * @param hcomp COMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_COMP_Start(COMP_HandleTypeDef *hcomp)
+{
+ __IO uint32_t wait_loop_index = 0UL;
+
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the COMP handle allocation and lock status */
+ if(hcomp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(__HAL_COMP_IS_LOCKED(hcomp))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
+
+ if(hcomp->State == HAL_COMP_STATE_READY)
+ {
+ /* Enable the selected comparator */
+ SET_BIT(hcomp->Instance->CFGR, COMP_CFGRx_EN);
+
+ /* Set HAL COMP handle state */
+ hcomp->State = HAL_COMP_STATE_BUSY;
+
+ /* Delay for COMP startup time */
+ /* Wait loop initialization and execution */
+ /* Note: Variable divided by 2 to compensate partially */
+ /* CPU processing cycles. */
+
+ wait_loop_index = (COMP_DELAY_STARTUP_US * (SystemCoreClock / (1000000UL * 2UL)));
+ while(wait_loop_index != 0UL)
+ {
+ wait_loop_index--;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Stop the comparator.
+ * @param hcomp COMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_COMP_Stop(COMP_HandleTypeDef *hcomp)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the COMP handle allocation and lock status */
+ if(hcomp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(__HAL_COMP_IS_LOCKED(hcomp))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
+
+ /* Check compliant states: HAL_COMP_STATE_READY or HAL_COMP_STATE_BUSY */
+ /* (all states except HAL_COMP_STATE_RESET and except locked status. */
+ if(hcomp->State != HAL_COMP_STATE_RESET)
+ {
+
+ /* Disable the selected comparator */
+ CLEAR_BIT(hcomp->Instance->CFGR, COMP_CFGRx_EN);
+
+ /* Set HAL COMP handle state */
+ hcomp->State = HAL_COMP_STATE_READY;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Enable the interrupt and start the comparator.
+ * @param hcomp COMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_COMP_Start_IT(COMP_HandleTypeDef *hcomp)
+{
+
+ __IO uint32_t wait_loop_index = 0UL;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the COMP handle allocation and lock status */
+ if(hcomp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(__HAL_COMP_IS_LOCKED(hcomp))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
+ /* Set HAL COMP handle state */
+ if(hcomp->State == HAL_COMP_STATE_READY)
+ {
+
+ /* Enable the selected comparator */
+ SET_BIT(hcomp->Instance->CFGR, COMP_CFGRx_EN);
+ /* Enable the Interrupt comparator */
+ SET_BIT(hcomp->Instance->CFGR, COMP_CFGRx_ITEN);
+
+ hcomp->State = HAL_COMP_STATE_BUSY;
+ /* Delay for COMP startup time */
+ /* Wait loop initialization and execution */
+ /* Note: Variable divided by 2 to compensate partially */
+ /* CPU processing cycles. */
+
+ wait_loop_index = (COMP_DELAY_STARTUP_US * (SystemCoreClock / (1000000UL * 2UL)));
+ while(wait_loop_index != 0UL)
+ {
+ wait_loop_index--;
+ }
+
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Disable the interrupt and Stop the comparator.
+ * @param hcomp COMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_COMP_Stop_IT(COMP_HandleTypeDef *hcomp)
+{
+ HAL_StatusTypeDef status;
+ /* Disable the EXTI Line interrupt mode */
+#if !defined (CORE_CM4)
+ CLEAR_BIT(EXTI->IMR1, COMP_GET_EXTI_LINE(hcomp->Instance));
+#else
+ CLEAR_BIT(EXTI->C2IMR1, COMP_GET_EXTI_LINE(hcomp->Instance));
+#endif
+ /* Disable the Interrupt comparator */
+ CLEAR_BIT(hcomp->Instance->CFGR, COMP_CFGRx_ITEN);
+
+ status = HAL_COMP_Stop(hcomp);
+
+ return status;
+
+}
+
+/**
+ * @brief Comparator IRQ Handler.
+ * @param hcomp COMP handle
+ * @retval HAL status
+ */
+void HAL_COMP_IRQHandler(COMP_HandleTypeDef *hcomp)
+{
+ /* Get the EXTI line corresponding to the selected COMP instance */
+ uint32_t exti_line = COMP_GET_EXTI_LINE(hcomp->Instance);
+
+
+#if defined(DUAL_CORE)
+ /* EXTI line interrupt detected */
+ if (HAL_GetCurrentCPUID() == CM7_CPUID)
+ {
+ /* Check COMP EXTI flag */
+ if(READ_BIT(EXTI->PR1, exti_line) != 0UL)
+ {
+ /* Check whether comparator is in independent or window mode */
+ if(READ_BIT(COMP12_COMMON->CFGR, COMP_CFGRx_WINMODE) != 0UL)
+ {
+ /* Clear COMP EXTI line pending bit of the pair of comparators */
+ /* in window mode. */
+ /* Note: Pair of comparators in window mode can both trig IRQ when */
+ /* input voltage is changing from "out of window" area */
+ /* (low or high ) to the other "out of window" area (high or low).*/
+ /* Both flags must be cleared to call comparator trigger */
+ /* callback is called once. */
+ WRITE_REG(EXTI->PR1, (COMP_EXTI_LINE_COMP1 | COMP_EXTI_LINE_COMP2));
+ }
+ else
+ {
+ /* Clear COMP EXTI line pending bit */
+ WRITE_REG(EXTI->PR1, exti_line);
+ }
+
+ /* COMP trigger user callback */
+#if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
+ hcomp->TriggerCallback(hcomp);
+#else
+ HAL_COMP_TriggerCallback(hcomp);
+#endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
+ }
+
+
+ }
+ else
+ {
+ /* Check COMP EXTI flag */
+ if(READ_BIT(EXTI->C2PR1, exti_line) != 0UL)
+ {
+ /* Check whether comparator is in independent or window mode */
+ if(READ_BIT(COMP12_COMMON->CFGR, COMP_CFGRx_WINMODE) != 0UL)
+ {
+ /* Clear COMP EXTI line pending bit of the pair of comparators */
+ /* in window mode. */
+ /* Note: Pair of comparators in window mode can both trig IRQ when */
+ /* input voltage is changing from "out of window" area */
+ /* (low or high ) to the other "out of window" area (high or low).*/
+ /* Both flags must be cleared to call comparator trigger */
+ /* callback is called once. */
+ WRITE_REG(EXTI->C2PR1, (COMP_EXTI_LINE_COMP1 | COMP_EXTI_LINE_COMP2));
+ }
+ else
+ {
+ /* Clear COMP EXTI line pending bit */
+ WRITE_REG(EXTI->C2PR1, exti_line);
+ }
+
+ /* COMP trigger user callback */
+#if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
+ hcomp->TriggerCallback(hcomp);
+#else
+ HAL_COMP_TriggerCallback(hcomp);
+#endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
+ }
+
+
+ }
+#else
+ /* Check COMP EXTI flag */
+ if(READ_BIT(EXTI->PR1, exti_line) != 0UL)
+ {
+ /* Check whether comparator is in independent or window mode */
+ if(READ_BIT(COMP12_COMMON->CFGR, COMP_CFGRx_WINMODE) != 0UL)
+ {
+ /* Clear COMP EXTI line pending bit of the pair of comparators */
+ /* in window mode. */
+ /* Note: Pair of comparators in window mode can both trig IRQ when */
+ /* input voltage is changing from "out of window" area */
+ /* (low or high ) to the other "out of window" area (high or low).*/
+ /* Both flags must be cleared to call comparator trigger */
+ /* callback is called once. */
+ WRITE_REG(EXTI->PR1, (COMP_EXTI_LINE_COMP1 | COMP_EXTI_LINE_COMP2));
+ }
+ else
+ {
+ /* Clear COMP EXTI line pending bit */
+ WRITE_REG(EXTI->PR1, exti_line);
+ }
+
+ /* COMP trigger user callback */
+#if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
+ hcomp->TriggerCallback(hcomp);
+#else
+ HAL_COMP_TriggerCallback(hcomp);
+#endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
+ }
+#endif /*DUAL_CORE*/
+
+ /* Get COMP interrupt source */
+ if (__HAL_COMP_GET_IT_SOURCE(hcomp, COMP_IT_EN) != RESET)
+ {
+
+ if((__HAL_COMP_GET_FLAG( COMP_FLAG_C1I)) != 0UL)
+ {
+ /* Clear the COMP channel 1 interrupt flag */
+ __HAL_COMP_CLEAR_C1IFLAG();
+
+ /* Disable COMP interrupt */
+ __HAL_COMP_DISABLE_IT(hcomp,COMP_IT_EN);
+
+ }
+ if((__HAL_COMP_GET_FLAG( COMP_FLAG_C2I)) != 0UL)
+ {
+ /* Clear the COMP channel 2 interrupt flag */
+ __HAL_COMP_CLEAR_C2IFLAG();
+
+ /* Disable COMP interrupt */
+ __HAL_COMP_DISABLE_IT(hcomp,COMP_IT_EN);
+
+ }
+
+ /* Change COMP state */
+ hcomp->State = HAL_COMP_STATE_READY;
+
+ /* COMP trigger user callback */
+#if (USE_HAL_COMP_REGISTER_CALLBACKS == 1)
+ hcomp->TriggerCallback(hcomp);
+#else
+ HAL_COMP_TriggerCallback(hcomp);
+#endif /* USE_HAL_COMP_REGISTER_CALLBACKS */
+ }
+
+
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Management functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the comparators.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Lock the selected comparator configuration.
+ * @note A system reset is required to unlock the comparator configuration.
+ * @param hcomp COMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_COMP_Lock(COMP_HandleTypeDef *hcomp)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the COMP handle allocation and lock status */
+ if(hcomp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(__HAL_COMP_IS_LOCKED(hcomp))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
+
+ /* Set HAL COMP handle state */
+ switch(hcomp->State)
+ {
+ case HAL_COMP_STATE_RESET:
+ hcomp->State = HAL_COMP_STATE_RESET_LOCKED;
+ break;
+ case HAL_COMP_STATE_READY:
+ hcomp->State = HAL_COMP_STATE_READY_LOCKED;
+ break;
+ default: /* HAL_COMP_STATE_BUSY */
+ hcomp->State = HAL_COMP_STATE_BUSY_LOCKED;
+ break;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Set the lock bit corresponding to selected comparator */
+ __HAL_COMP_LOCK(hcomp);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Return the output level (high or low) of the selected comparator.
+ * @note The output level depends on the selected polarity.
+ * If the polarity is not inverted:
+ * - Comparator output is low when the input plus is at a lower
+ * voltage than the input minus
+ * - Comparator output is high when the input plus is at a higher
+ * voltage than the input minus
+ * If the polarity is inverted:
+ * - Comparator output is high when the input plus is at a lower
+ * voltage than the input minus
+ * - Comparator output is low when the input plus is at a higher
+ * voltage than the input minus
+ * @param hcomp COMP handle
+ * @retval Returns the selected comparator output level:
+ * @arg @ref COMP_OUTPUT_LEVEL_LOW
+ * @arg @ref COMP_OUTPUT_LEVEL_HIGH
+ *
+ */
+uint32_t HAL_COMP_GetOutputLevel(COMP_HandleTypeDef *hcomp)
+{
+ /* Check the parameter */
+ assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
+
+ if (hcomp->Instance == COMP1)
+ {
+ return (uint32_t)(READ_BIT(COMP12->SR, COMP_SR_C1VAL));
+ }
+ else
+ {
+ return (uint32_t)((READ_BIT(COMP12->SR, COMP_SR_C2VAL))>> 1UL);
+ }
+}
+
+/**
+ * @brief Comparator trigger callback.
+ * @param hcomp COMP handle
+ * @retval None
+ */
+__weak void HAL_COMP_TriggerCallback(COMP_HandleTypeDef *hcomp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcomp);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_COMP_TriggerCallback should be implemented in the user file
+ */
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Exported_Functions_Group4 Peripheral State functions
+ * @brief Peripheral State functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection permit to get in run-time the status of the peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the COMP handle state.
+ * @param hcomp COMP handle
+ * @retval HAL state
+ */
+HAL_COMP_StateTypeDef HAL_COMP_GetState(COMP_HandleTypeDef *hcomp)
+{
+ /* Check the COMP handle allocation */
+ if(hcomp == NULL)
+ {
+ return HAL_COMP_STATE_RESET;
+ }
+
+ /* Check the parameter */
+ assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
+
+ /* Return HAL COMP handle state */
+ return hcomp->State;
+}
+
+/**
+ * @brief Return the COMP error code.
+ * @param hcomp COMP handle
+ * @retval COMP error code
+ */
+uint32_t HAL_COMP_GetError(COMP_HandleTypeDef *hcomp)
+{
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_INSTANCE(hcomp->Instance));
+
+ return hcomp->ErrorCode;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_COMP_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_cortex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_cortex.c
new file mode 100644
index 0000000000..631f432f7e
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_cortex.c
@@ -0,0 +1,533 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 Initializes and configures the Region and the memory to be protected.
+ * @param MPU_Init Pointer to a MPU_Region_InitTypeDef structure that contains
+ * the initialization and configuration information.
+ * @retval None
+ */
+void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init)
+{
+ /* Check the parameters */
+ assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number));
+ assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable));
+
+ /* Set the Region number */
+ MPU->RNR = MPU_Init->Number;
+
+ if ((MPU_Init->Enable) != 0UL)
+ {
+ /* Check the parameters */
+ assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec));
+ assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission));
+ assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField));
+ assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable));
+ assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable));
+ assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable));
+ assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable));
+ assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size));
+
+ MPU->RBAR = MPU_Init->BaseAddress;
+ MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) |
+ ((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) |
+ ((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) |
+ ((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) |
+ ((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) |
+ ((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) |
+ ((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) |
+ ((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) |
+ ((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos);
+ }
+ else
+ {
+ MPU->RBAR = 0x00;
+ MPU->RASR = 0x00;
+ }
+}
+#endif /* __MPU_PRESENT */
+
+/**
+ * @brief Gets the priority grouping field from the NVIC Interrupt Controller.
+ * @retval Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field)
+ */
+uint32_t HAL_NVIC_GetPriorityGrouping(void)
+{
+ /* Get the PRIGROUP[10:8] field value */
+ return NVIC_GetPriorityGrouping();
+}
+
+/**
+ * @brief Gets the priority of an interrupt.
+ * @param IRQn External interrupt number.
+ * This parameter can be an enumerator of IRQn_Type enumeration
+ * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_crc.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_crc.c
new file mode 100644
index 0000000000..5d12b7f610
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_crc.c
@@ -0,0 +1,518 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_crc.c
+ * @author MCD Application Team
+ * @brief CRC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Cyclic Redundancy Check (CRC) peripheral:
+ * + Initialization and de-initialization functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ (+) Enable CRC AHB clock using __HAL_RCC_CRC_CLK_ENABLE();
+ (+) Initialize CRC calculator
+ (++) specify generating polynomial (peripheral default or non-default one)
+ (++) specify initialization value (peripheral default or non-default one)
+ (++) specify input data format
+ (++) specify input or output data inversion mode if any
+ (+) Use HAL_CRC_Accumulate() function to compute the CRC value of the
+ input data buffer starting with the previously computed CRC as
+ initialization value
+ (+) Use HAL_CRC_Calculate() function to compute the CRC value of the
+ input data buffer starting with the defined initialization value
+ (default or non-default) to initiate CRC calculation
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup CRC CRC
+ * @brief CRC HAL module driver.
+ * @{
+ */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup CRC_Private_Functions CRC Private Functions
+ * @{
+ */
+static uint32_t CRC_Handle_8(CRC_HandleTypeDef *hcrc, uint8_t pBuffer[], uint32_t BufferLength);
+static uint32_t CRC_Handle_16(CRC_HandleTypeDef *hcrc, uint16_t pBuffer[], uint32_t BufferLength);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup CRC_Exported_Functions CRC Exported Functions
+ * @{
+ */
+
+/** @defgroup CRC_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 the CRC according to the specified parameters
+ in the CRC_InitTypeDef and create the associated handle
+ (+) DeInitialize the CRC peripheral
+ (+) Initialize the CRC MSP (MCU Specific Package)
+ (+) DeInitialize the CRC MSP
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the CRC according to the specified
+ * parameters in the CRC_InitTypeDef and create the associated handle.
+ * @param hcrc CRC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRC_Init(CRC_HandleTypeDef *hcrc)
+{
+ /* Check the CRC handle allocation */
+ if (hcrc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
+
+ if (hcrc->State == HAL_CRC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hcrc->Lock = HAL_UNLOCKED;
+ /* Init the low level hardware */
+ HAL_CRC_MspInit(hcrc);
+ }
+
+ hcrc->State = HAL_CRC_STATE_BUSY;
+
+ /* check whether or not non-default generating polynomial has been
+ * picked up by user */
+ assert_param(IS_DEFAULT_POLYNOMIAL(hcrc->Init.DefaultPolynomialUse));
+ if (hcrc->Init.DefaultPolynomialUse == DEFAULT_POLYNOMIAL_ENABLE)
+ {
+ /* initialize peripheral with default generating polynomial */
+ WRITE_REG(hcrc->Instance->POL, DEFAULT_CRC32_POLY);
+ MODIFY_REG(hcrc->Instance->CR, CRC_CR_POLYSIZE, CRC_POLYLENGTH_32B);
+ }
+ else
+ {
+ /* initialize CRC peripheral with generating polynomial defined by user */
+ if (HAL_CRCEx_Polynomial_Set(hcrc, hcrc->Init.GeneratingPolynomial, hcrc->Init.CRCLength) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ /* check whether or not non-default CRC initial value has been
+ * picked up by user */
+ assert_param(IS_DEFAULT_INIT_VALUE(hcrc->Init.DefaultInitValueUse));
+ if (hcrc->Init.DefaultInitValueUse == DEFAULT_INIT_VALUE_ENABLE)
+ {
+ WRITE_REG(hcrc->Instance->INIT, DEFAULT_CRC_INITVALUE);
+ }
+ else
+ {
+ WRITE_REG(hcrc->Instance->INIT, hcrc->Init.InitValue);
+ }
+
+
+ /* set input data inversion mode */
+ assert_param(IS_CRC_INPUTDATA_INVERSION_MODE(hcrc->Init.InputDataInversionMode));
+ MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_IN, hcrc->Init.InputDataInversionMode);
+
+ /* set output data inversion mode */
+ assert_param(IS_CRC_OUTPUTDATA_INVERSION_MODE(hcrc->Init.OutputDataInversionMode));
+ MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_OUT, hcrc->Init.OutputDataInversionMode);
+
+ /* makes sure the input data format (bytes, halfwords or words stream)
+ * is properly specified by user */
+ assert_param(IS_CRC_INPUTDATA_FORMAT(hcrc->InputDataFormat));
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the CRC peripheral.
+ * @param hcrc CRC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRC_DeInit(CRC_HandleTypeDef *hcrc)
+{
+ /* Check the CRC handle allocation */
+ if (hcrc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
+
+ /* Check the CRC peripheral state */
+ if (hcrc->State == HAL_CRC_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_BUSY;
+
+ /* Reset CRC calculation unit */
+ __HAL_CRC_DR_RESET(hcrc);
+
+ /* Reset IDR register content */
+ CLEAR_BIT(hcrc->Instance->IDR, CRC_IDR_IDR);
+
+ /* DeInit the low level hardware */
+ HAL_CRC_MspDeInit(hcrc);
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_RESET;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcrc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the CRC MSP.
+ * @param hcrc CRC handle
+ * @retval None
+ */
+__weak void HAL_CRC_MspInit(CRC_HandleTypeDef *hcrc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcrc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CRC_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the CRC MSP.
+ * @param hcrc CRC handle
+ * @retval None
+ */
+__weak void HAL_CRC_MspDeInit(CRC_HandleTypeDef *hcrc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcrc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CRC_MspDeInit can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CRC_Exported_Functions_Group2 Peripheral Control functions
+ * @brief management functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
+ using combination of the previous CRC value and the new one.
+
+ [..] or
+
+ (+) compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
+ independently of the previous CRC value.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
+ * starting with the previously computed CRC as initialization value.
+ * @param hcrc CRC handle
+ * @param pBuffer pointer to the input data buffer, exact input data format is
+ * provided by hcrc->InputDataFormat.
+ * @param BufferLength input data buffer length (number of bytes if pBuffer
+ * type is * uint8_t, number of half-words if pBuffer type is * uint16_t,
+ * number of words if pBuffer type is * uint32_t).
+ * @note By default, the API expects a uint32_t pointer as input buffer parameter.
+ * Input buffer pointers with other types simply need to be cast in uint32_t
+ * and the API will internally adjust its input data processing based on the
+ * handle field hcrc->InputDataFormat.
+ * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
+ */
+uint32_t HAL_CRC_Accumulate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
+{
+ uint32_t index; /* CRC input data buffer index */
+ uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_BUSY;
+
+ switch (hcrc->InputDataFormat)
+ {
+ case CRC_INPUTDATA_FORMAT_WORDS:
+ /* Enter Data to the CRC calculator */
+ for (index = 0U; index < BufferLength; index++)
+ {
+ hcrc->Instance->DR = pBuffer[index];
+ }
+ temp = hcrc->Instance->DR;
+ break;
+
+ case CRC_INPUTDATA_FORMAT_BYTES:
+ temp = CRC_Handle_8(hcrc, (uint8_t *)pBuffer, BufferLength);
+ break;
+
+ case CRC_INPUTDATA_FORMAT_HALFWORDS:
+ temp = CRC_Handle_16(hcrc, (uint16_t *)(void *)pBuffer, BufferLength); /* Derogation MisraC2012 R.11.5 */
+ break;
+ default:
+ break;
+ }
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_READY;
+
+ /* Return the CRC computed value */
+ return temp;
+}
+
+/**
+ * @brief Compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
+ * starting with hcrc->Instance->INIT as initialization value.
+ * @param hcrc CRC handle
+ * @param pBuffer pointer to the input data buffer, exact input data format is
+ * provided by hcrc->InputDataFormat.
+ * @param BufferLength input data buffer length (number of bytes if pBuffer
+ * type is * uint8_t, number of half-words if pBuffer type is * uint16_t,
+ * number of words if pBuffer type is * uint32_t).
+ * @note By default, the API expects a uint32_t pointer as input buffer parameter.
+ * Input buffer pointers with other types simply need to be cast in uint32_t
+ * and the API will internally adjust its input data processing based on the
+ * handle field hcrc->InputDataFormat.
+ * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
+ */
+uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
+{
+ uint32_t index; /* CRC input data buffer index */
+ uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_BUSY;
+
+ /* Reset CRC Calculation Unit (hcrc->Instance->INIT is
+ * written in hcrc->Instance->DR) */
+ __HAL_CRC_DR_RESET(hcrc);
+
+ switch (hcrc->InputDataFormat)
+ {
+ case CRC_INPUTDATA_FORMAT_WORDS:
+ /* Enter 32-bit input data to the CRC calculator */
+ for (index = 0U; index < BufferLength; index++)
+ {
+ hcrc->Instance->DR = pBuffer[index];
+ }
+ temp = hcrc->Instance->DR;
+ break;
+
+ case CRC_INPUTDATA_FORMAT_BYTES:
+ /* Specific 8-bit input data handling */
+ temp = CRC_Handle_8(hcrc, (uint8_t *)pBuffer, BufferLength);
+ break;
+
+ case CRC_INPUTDATA_FORMAT_HALFWORDS:
+ /* Specific 16-bit input data handling */
+ temp = CRC_Handle_16(hcrc, (uint16_t *)(void *)pBuffer, BufferLength); /* Derogation MisraC2012 R.11.5 */
+ break;
+
+ default:
+ break;
+ }
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_READY;
+
+ /* Return the CRC computed value */
+ return temp;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CRC_Exported_Functions_Group3 Peripheral State functions
+ * @brief Peripheral State functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the CRC handle state.
+ * @param hcrc CRC handle
+ * @retval HAL state
+ */
+HAL_CRC_StateTypeDef HAL_CRC_GetState(CRC_HandleTypeDef *hcrc)
+{
+ /* Return CRC handle state */
+ return hcrc->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup CRC_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Enter 8-bit input data to the CRC calculator.
+ * Specific data handling to optimize processing time.
+ * @param hcrc CRC handle
+ * @param pBuffer pointer to the input data buffer
+ * @param BufferLength input data buffer length
+ * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
+ */
+static uint32_t CRC_Handle_8(CRC_HandleTypeDef *hcrc, uint8_t pBuffer[], uint32_t BufferLength)
+{
+ uint32_t i; /* input data buffer index */
+ uint16_t data;
+ __IO uint16_t *pReg;
+
+ /* Processing time optimization: 4 bytes are entered in a row with a single word write,
+ * last bytes must be carefully fed to the CRC calculator to ensure a correct type
+ * handling by the peripheral */
+ for (i = 0U; i < (BufferLength / 4U); i++)
+ {
+ hcrc->Instance->DR = ((uint32_t)pBuffer[4U * i] << 24U) | \
+ ((uint32_t)pBuffer[(4U * i) + 1U] << 16U) | \
+ ((uint32_t)pBuffer[(4U * i) + 2U] << 8U) | \
+ (uint32_t)pBuffer[(4U * i) + 3U];
+ }
+ /* last bytes specific handling */
+ if ((BufferLength % 4U) != 0U)
+ {
+ if ((BufferLength % 4U) == 1U)
+ {
+ *(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[4U * i]; /* Derogation MisraC2012 R.11.5 */
+ }
+ if ((BufferLength % 4U) == 2U)
+ {
+ data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];
+ pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
+ *pReg = data;
+ }
+ if ((BufferLength % 4U) == 3U)
+ {
+ data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];
+ pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
+ *pReg = data;
+
+ *(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[(4U * i) + 2U]; /* Derogation MisraC2012 R.11.5 */
+ }
+ }
+
+ /* Return the CRC computed value */
+ return hcrc->Instance->DR;
+}
+
+/**
+ * @brief Enter 16-bit input data to the CRC calculator.
+ * Specific data handling to optimize processing time.
+ * @param hcrc CRC handle
+ * @param pBuffer pointer to the input data buffer
+ * @param BufferLength input data buffer length
+ * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
+ */
+static uint32_t CRC_Handle_16(CRC_HandleTypeDef *hcrc, uint16_t pBuffer[], uint32_t BufferLength)
+{
+ uint32_t i; /* input data buffer index */
+ __IO uint16_t *pReg;
+
+ /* Processing time optimization: 2 HalfWords are entered in a row with a single word write,
+ * in case of odd length, last HalfWord must be carefully fed to the CRC calculator to ensure
+ * a correct type handling by the peripheral */
+ for (i = 0U; i < (BufferLength / 2U); i++)
+ {
+ hcrc->Instance->DR = ((uint32_t)pBuffer[2U * i] << 16U) | (uint32_t)pBuffer[(2U * i) + 1U];
+ }
+ if ((BufferLength % 2U) != 0U)
+ {
+ pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
+ *pReg = pBuffer[2U * i];
+ }
+
+ /* Return the CRC computed value */
+ return hcrc->Instance->DR;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_CRC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_crc_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_crc_ex.c
new file mode 100644
index 0000000000..2ce184e5d5
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_crc_ex.c
@@ -0,0 +1,225 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_crc_ex.c
+ * @author MCD Application Team
+ * @brief Extended CRC HAL module driver.
+ * This file provides firmware functions to manage the extended
+ * functionalities of the CRC peripheral.
+ *
+ @verbatim
+================================================================================
+ ##### How to use this driver #####
+================================================================================
+ [..]
+ (+) Set user-defined generating polynomial thru HAL_CRCEx_Polynomial_Set()
+ (+) Configure Input or Output data inversion
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup CRCEx CRCEx
+ * @brief CRC Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup CRCEx_Exported_Functions CRC Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup CRCEx_Exported_Functions_Group1 Extended Initialization/de-initialization functions
+ * @brief Extended Initialization and Configuration functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure the generating polynomial
+ (+) Configure the input data inversion
+ (+) Configure the output data inversion
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Initialize the CRC polynomial if different from default one.
+ * @param hcrc CRC handle
+ * @param Pol CRC generating polynomial (7, 8, 16 or 32-bit long).
+ * This parameter is written in normal representation, e.g.
+ * @arg for a polynomial of degree 7, X^7 + X^6 + X^5 + X^2 + 1 is written 0x65
+ * @arg for a polynomial of degree 16, X^16 + X^12 + X^5 + 1 is written 0x1021
+ * @param PolyLength CRC polynomial length.
+ * This parameter can be one of the following values:
+ * @arg @ref CRC_POLYLENGTH_7B 7-bit long CRC (generating polynomial of degree 7)
+ * @arg @ref CRC_POLYLENGTH_8B 8-bit long CRC (generating polynomial of degree 8)
+ * @arg @ref CRC_POLYLENGTH_16B 16-bit long CRC (generating polynomial of degree 16)
+ * @arg @ref CRC_POLYLENGTH_32B 32-bit long CRC (generating polynomial of degree 32)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRCEx_Polynomial_Set(CRC_HandleTypeDef *hcrc, uint32_t Pol, uint32_t PolyLength)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t msb = 31U; /* polynomial degree is 32 at most, so msb is initialized to max value */
+
+ /* Check the parameters */
+ assert_param(IS_CRC_POL_LENGTH(PolyLength));
+
+ /* check polynomial definition vs polynomial size:
+ * polynomial length must be aligned with polynomial
+ * definition. HAL_ERROR is reported if Pol degree is
+ * larger than that indicated by PolyLength.
+ * Look for MSB position: msb will contain the degree of
+ * the second to the largest polynomial member. E.g., for
+ * X^7 + X^6 + X^5 + X^2 + 1, msb = 6. */
+ while ((msb-- > 0U) && ((Pol & ((uint32_t)(0x1U) << (msb & 0x1FU))) == 0U))
+ {
+ }
+
+ switch (PolyLength)
+ {
+ case CRC_POLYLENGTH_7B:
+ if (msb >= HAL_CRC_LENGTH_7B)
+ {
+ status = HAL_ERROR;
+ }
+ break;
+ case CRC_POLYLENGTH_8B:
+ if (msb >= HAL_CRC_LENGTH_8B)
+ {
+ status = HAL_ERROR;
+ }
+ break;
+ case CRC_POLYLENGTH_16B:
+ if (msb >= HAL_CRC_LENGTH_16B)
+ {
+ status = HAL_ERROR;
+ }
+ break;
+
+ case CRC_POLYLENGTH_32B:
+ /* no polynomial definition vs. polynomial length issue possible */
+ break;
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+ if (status == HAL_OK)
+ {
+ /* set generating polynomial */
+ WRITE_REG(hcrc->Instance->POL, Pol);
+
+ /* set generating polynomial size */
+ MODIFY_REG(hcrc->Instance->CR, CRC_CR_POLYSIZE, PolyLength);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Set the Reverse Input data mode.
+ * @param hcrc CRC handle
+ * @param InputReverseMode Input Data inversion mode.
+ * This parameter can be one of the following values:
+ * @arg @ref CRC_INPUTDATA_INVERSION_NONE no change in bit order (default value)
+ * @arg @ref CRC_INPUTDATA_INVERSION_BYTE Byte-wise bit reversal
+ * @arg @ref CRC_INPUTDATA_INVERSION_HALFWORD HalfWord-wise bit reversal
+ * @arg @ref CRC_INPUTDATA_INVERSION_WORD Word-wise bit reversal
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRCEx_Input_Data_Reverse(CRC_HandleTypeDef *hcrc, uint32_t InputReverseMode)
+{
+ /* Check the parameters */
+ assert_param(IS_CRC_INPUTDATA_INVERSION_MODE(InputReverseMode));
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_BUSY;
+
+ /* set input data inversion mode */
+ MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_IN, InputReverseMode);
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the Reverse Output data mode.
+ * @param hcrc CRC handle
+ * @param OutputReverseMode Output Data inversion mode.
+ * This parameter can be one of the following values:
+ * @arg @ref CRC_OUTPUTDATA_INVERSION_DISABLE no CRC inversion (default value)
+ * @arg @ref CRC_OUTPUTDATA_INVERSION_ENABLE bit-level inversion (e.g. for a 8-bit CRC: 0xB5 becomes 0xAD)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRCEx_Output_Data_Reverse(CRC_HandleTypeDef *hcrc, uint32_t OutputReverseMode)
+{
+ /* Check the parameters */
+ assert_param(IS_CRC_OUTPUTDATA_INVERSION_MODE(OutputReverseMode));
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_BUSY;
+
+ /* set output data inversion mode */
+ MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_OUT, OutputReverseMode);
+
+ /* Change CRC peripheral state */
+ hcrc->State = HAL_CRC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+#endif /* HAL_CRC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_cryp.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_cryp.c
new file mode 100644
index 0000000000..abf8584a2c
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_cryp.c
@@ -0,0 +1,5145 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_cryp.c
+ * @author MCD Application Team
+ * @brief CRYP HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Cryptography (CRYP) peripheral:
+ * + Initialization and de-initialization functions
+ * + AES processing functions
+ * + DES processing functions
+ * + TDES processing functions
+ * + DMA callback functions
+ * + CRYP IRQ handler management
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The CRYP HAL driver can be used in CRYP IP as follows:
+
+ (#)Initialize the CRYP low level resources by implementing the HAL_CRYP_MspInit():
+ (##) Enable the CRYP interface clock using __HAL_RCC_CRYP_CLK_ENABLE()
+ (##) In case of using interrupts (e.g. HAL_CRYP_Encrypt_IT())
+ (+++) Configure the CRYP interrupt priority using HAL_NVIC_SetPriority()
+ (+++) Enable the CRYP IRQ handler using HAL_NVIC_EnableIRQ()
+ (+++) In CRYP IRQ handler, call HAL_CRYP_IRQHandler()
+ (##) In case of using DMA to control data transfer (e.g. HAL_CRYP_Encrypt_DMA())
+ (+++) Enable the DMAx interface clock using __RCC_DMAx_CLK_ENABLE()
+ (+++) Configure and enable two DMA streams one for managing data transfer from
+ memory to peripheral (input stream) and another stream for managing data
+ transfer from peripheral to memory (output stream)
+ (+++) Associate the initialized DMA handle to the CRYP DMA handle
+ using __HAL_LINKDMA()
+ (+++) Configure the priority and enable the NVIC for the transfer complete
+ interrupt on the two DMA Streams. The output stream should have higher
+ priority than the input stream HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ()
+
+ (#)Initialize the CRYP according to the specified parameters :
+ (##) The data type: 1-bit, 8-bit, 16-bit or 32-bit.
+ (##) The key size: 128, 192 or 256.
+ (##) The AlgoMode DES/ TDES Algorithm ECB/CBC or AES Algorithm ECB/CBC/CTR/GCM or CCM.
+ (##) The initialization vector (counter). It is not used in ECB mode.
+ (##) The key buffer used for encryption/decryption.
+ (##) The Header used only in AES GCM and CCM Algorithm for authentication.
+ (##) The HeaderSize The size of header buffer in word.
+ (##) The B0 block is the first authentication block used only in AES CCM mode.
+
+ (#)Three processing (encryption/decryption) functions are available:
+ (##) Polling mode: encryption and decryption APIs are blocking functions
+ i.e. they process the data and wait till the processing is finished,
+ e.g. HAL_CRYP_Encrypt & HAL_CRYP_Decrypt
+ (##) Interrupt mode: encryption and decryption APIs are not blocking functions
+ i.e. they process the data under interrupt,
+ e.g. HAL_CRYP_Encrypt_IT & HAL_CRYP_Decrypt_IT
+ (##) DMA mode: encryption and decryption APIs are not blocking functions
+ i.e. the data transfer is ensured by DMA,
+ e.g. HAL_CRYP_Encrypt_DMA & HAL_CRYP_Decrypt_DMA
+
+ (#)When the processing function is called at first time after HAL_CRYP_Init()
+ the CRYP peripheral is configured and processes the buffer in input.
+ At second call, no need to Initialize the CRYP, user have to get current configuration via
+ HAL_CRYP_GetConfig() API, then only HAL_CRYP_SetConfig() is requested to set
+ new parametres, finally user can start encryption/decryption.
+
+ (#)Call HAL_CRYP_DeInit() to deinitialize the CRYP peripheral.
+
+ (#)To process a single message with consecutive calls to HAL_CRYP_Encrypt() or HAL_CRYP_Decrypt()
+ without having to configure again the Key or the Initialization Vector between each API call,
+ the field KeyIVConfigSkip of the initialization structure must be set to CRYP_KEYIVCONFIG_ONCE.
+ Same is true for consecutive calls of HAL_CRYP_Encrypt_IT(), HAL_CRYP_Decrypt_IT(), HAL_CRYP_Encrypt_DMA()
+ or HAL_CRYP_Decrypt_DMA().
+
+ [..]
+ The cryptographic processor supports following standards:
+ (#) The data encryption standard (DES) and Triple-DES (TDES) supported only by CRYP1 IP:
+ (##)64-bit data block processing
+ (##) chaining modes supported :
+ (+++) Electronic Code Book(ECB)
+ (+++) Cipher Block Chaining (CBC)
+ (##) keys length supported :64-bit, 128-bit and 192-bit.
+ (#) The advanced encryption standard (AES) supported by CRYP1:
+ (##)128-bit data block processing
+ (##) chaining modes supported :
+ (+++) Electronic Code Book(ECB)
+ (+++) Cipher Block Chaining (CBC)
+ (+++) Counter mode (CTR)
+ (+++) Galois/counter mode (GCM/GMAC)
+ (+++) Counter with Cipher Block Chaining-Message(CCM)
+ (##) keys length Supported :
+ (+++) for CRYP1 IP: 128-bit, 192-bit and 256-bit.
+
+ [..] This section describes the AES Galois/counter mode (GCM) supported by both CRYP1 IP:
+ (#) Algorithm supported :
+ (##) Galois/counter mode (GCM)
+ (##) Galois message authentication code (GMAC) :is exactly the same as
+ GCM algorithm composed only by an header.
+ (#) Four phases are performed in GCM :
+ (##) Init phase: IP prepares the GCM hash subkey (H) and do the IV processing
+ (##) Header phase: IP processes the Additional Authenticated Data (AAD), with hash
+ computation only.
+ (##) Payload phase: IP processes the plaintext (P) with hash computation + keystream
+ encryption + data XORing. It works in a similar way for ciphertext (C).
+ (##) Final phase: IP generates the authenticated tag (T) using the last block of data.
+ (#) structure of message construction in GCM is defined as below :
+ (##) 16 bytes Initial Counter Block (ICB)composed of IV and counter
+ (##) The authenticated header A (also knows as Additional Authentication Data AAD)
+ this part of the message is only authenticated, not encrypted.
+ (##) The plaintext message P is both authenticated and encrypted as ciphertext.
+ GCM standard specifies that ciphertext has same bit length as the plaintext.
+ (##) The last block is composed of the length of A (on 64 bits) and the length of ciphertext
+ (on 64 bits)
+
+ [..] This section describe The AES Counter with Cipher Block Chaining-Message
+ Authentication Code (CCM) supported by both CRYP1 IP:
+ (#) Specific parameters for CCM :
+
+ (##) B0 block : According to NIST Special Publication 800-38C,
+ The first block B0 is formatted as follows, where l(m) is encoded in
+ most-significant-byte first order(see below table 3)
+
+ (+++) Q: a bit string representation of the octet length of P (plaintext)
+ (+++) q The octet length of the binary representation of the octet length of the payload
+ (+++) A nonce (N), n The octet length of the where n+q=15.
+ (+++) Flags: most significant octet containing four flags for control information,
+ (+++) t The octet length of the MAC.
+ (##) B1 block (header) : associated data length(a) concatenated with Associated Data (A)
+ the associated data length expressed in bytes (a) defined as below:
+ (+++) If 0 < a < 216-28, then it is encoded as [a]16, i.e. two octets
+ (+++) If 216-28 < a < 232, then it is encoded as 0xff || 0xfe || [a]32, i.e. six octets
+ (+++) If 232 < a < 264, then it is encoded as 0xff || 0xff || [a]64, i.e. ten octets
+ (##) CTRx block : control blocks
+ (+++) Generation of CTR1 from first block B0 information :
+ equal to B0 with first 5 bits zeroed and most significant bits storing octet
+ length of P also zeroed, then incremented by one ( see below Table 4)
+ (+++) Generation of CTR0: same as CTR1 with bit[0] set to zero.
+
+ (#) Four phases are performed in CCM for CRYP1 IP:
+ (##) Init phase: IP prepares the GCM hash subkey (H) and do the IV processing
+ (##) Header phase: IP processes the Additional Authenticated Data (AAD), with hash
+ computation only.
+ (##) Payload phase: IP processes the plaintext (P) with hash computation + keystream
+ encryption + data XORing. It works in a similar way for ciphertext (C).
+ (##) Final phase: IP generates the authenticated tag (T) using the last block of data.
+
+ *** Callback registration ***
+ =============================
+
+ [..]
+ The compilation define USE_HAL_CRYP_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions @ref HAL_CRYP_RegisterCallback() or HAL_CRYP_RegisterXXXCallback()
+ to register an interrupt callback.
+
+ [..]
+ Function @ref HAL_CRYP_RegisterCallback() allows to register following callbacks:
+ (+) InCpltCallback : Input FIFO transfer completed callback.
+ (+) OutCpltCallback : Output FIFO transfer completed callback.
+ (+) ErrorCallback : callback for error detection.
+ (+) MspInitCallback : CRYP MspInit.
+ (+) MspDeInitCallback : CRYP MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function @ref HAL_CRYP_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ @ref HAL_CRYP_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) InCpltCallback : Input FIFO transfer completed callback.
+ (+) OutCpltCallback : Output FIFO transfer completed callback.
+ (+) ErrorCallback : callback for error detection.
+ (+) MspInitCallback : CRYP MspInit.
+ (+) MspDeInitCallback : CRYP MspDeInit.
+
+ [..]
+ By default, after the @ref HAL_CRYP_Init() and when the state is HAL_CRYP_STATE_RESET
+ all callbacks are set to the corresponding weak functions :
+ examples @ref HAL_CRYP_InCpltCallback() , @ref HAL_CRYP_OutCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak function in the @ref HAL_CRYP_Init()/ @ref HAL_CRYP_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ if not, MspInit or MspDeInit are not null, the @ref HAL_CRYP_Init() / @ref HAL_CRYP_DeInit()
+ keep and use the user MspInit/MspDeInit functions (registered beforehand)
+
+ [..]
+ Callbacks can be registered/unregistered in HAL_CRYP_STATE_READY state only.
+ Exception done MspInit/MspDeInit callbacks that can be registered/unregistered
+ in HAL_CRYP_STATE_READY or HAL_CRYP_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 @ref HAL_CRYP_RegisterCallback() before calling @ref HAL_CRYP_DeInit()
+ or @ref HAL_CRYP_Init() function.
+
+ [..]
+ When The compilation define USE_HAL_CRYP_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
+
+ Table 1. Initial Counter Block (ICB)
+ +-------------------------------------------------------+
+ | Initialization vector (IV) | Counter |
+ |----------------|----------------|-----------|---------|
+ 127 95 63 31 0
+
+
+ Bit Number Register Contents
+ ---------- --------------- -----------
+ 127 ...96 CRYP_IV1R[31:0] ICB[127:96]
+ 95 ...64 CRYP_IV1L[31:0] B0[95:64]
+ 63 ... 32 CRYP_IV0R[31:0] ICB[63:32]
+ 31 ... 0 CRYP_IV0L[31:0] ICB[31:0], where 32-bit counter= 0x2
+
+ Table 2. GCM last block definition
+
+ +-------------------------------------------------------------------+
+ | Bit[0] | Bit[32] | Bit[64] | Bit[96] |
+ |-----------|--------------------|-----------|----------------------|
+ | 0x0 | Header length[31:0]| 0x0 | Payload length[31:0] |
+ |-----------|--------------------|-----------|----------------------|
+
+ Table 3. B0 block
+ Octet Number Contents
+ ------------ ---------
+ 0 Flags
+ 1 ... 15-q Nonce N
+ 16-q ... 15 Q
+
+ the Flags field is formatted as follows:
+
+ Bit Number Contents
+ ---------- ----------------------
+ 7 Reserved (always zero)
+ 6 Adata
+ 5 ... 3 (t-2)/2
+ 2 ... 0 [q-1]3
+
+ Table 4. CTRx block
+ Bit Number Register Contents
+ ---------- --------------- -----------
+ 127 ...96 CRYP_IV1R[31:0] B0[127:96], where Q length bits are set to 0, except for
+ bit 0 that is set to 1
+ 95 ...64 CRYP_IV1L[31:0] B0[95:64]
+ 63 ... 32 CRYP_IV0R[31:0] B0[63:32]
+ 31 ... 0 CRYP_IV0L[31:0] B0[31:0], where flag bits set to 0
+
+
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#if defined (CRYP)
+
+/** @defgroup CRYP CRYP
+ * @brief CRYP HAL module driver.
+ * @{
+ */
+
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup CRYP_Private_Defines
+ * @{
+ */
+#define CRYP_TIMEOUT_KEYPREPARATION 82U /*The latency of key preparation operation is 82 clock cycles.*/
+#define CRYP_TIMEOUT_GCMCCMINITPHASE 299U /* The latency of GCM/CCM init phase to prepare hash subkey is 299 clock cycles.*/
+#define CRYP_TIMEOUT_GCMCCMHEADERPHASE 290U /* The latency of GCM/CCM header phase is 290 clock cycles.*/
+
+#define CRYP_PHASE_READY 0x00000001U /*!< CRYP peripheral is ready for initialization. */
+#define CRYP_PHASE_PROCESS 0x00000002U /*!< CRYP peripheral is in processing phase */
+
+#define CRYP_PHASE_INIT 0x00000000U /*!< GCM/GMAC (or CCM) init phase */
+#define CRYP_PHASE_HEADER CRYP_CR_GCM_CCMPH_0 /*!< GCM/GMAC or CCM header phase */
+#define CRYP_PHASE_PAYLOAD CRYP_CR_GCM_CCMPH_1 /*!< GCM(/CCM) payload phase */
+#define CRYP_PHASE_FINAL CRYP_CR_GCM_CCMPH /*!< GCM/GMAC or CCM final phase */
+#define CRYP_OPERATINGMODE_ENCRYPT 0x00000000U /*!< Encryption mode */
+#define CRYP_OPERATINGMODE_DECRYPT CRYP_CR_ALGODIR /*!< Decryption */
+
+
+/* CTR1 information to use in CCM algorithm */
+#define CRYP_CCM_CTR1_0 0x07FFFFFFU
+#define CRYP_CCM_CTR1_1 0xFFFFFF00U
+#define CRYP_CCM_CTR1_2 0x00000001U
+
+/**
+ * @}
+ */
+
+
+/* Private macro -------------------------------------------------------------*/
+/** @addtogroup CRYP_Private_Macros
+ * @{
+ */
+
+#define CRYP_SET_PHASE(__HANDLE__, __PHASE__) do{(__HANDLE__)->Instance->CR &= (uint32_t)(~CRYP_CR_GCM_CCMPH);\
+ (__HANDLE__)->Instance->CR |= (uint32_t)(__PHASE__);\
+ }while(0)
+
+#define HAL_CRYP_FIFO_FLUSH(__HANDLE__) ((__HANDLE__)->Instance->CR |= CRYP_CR_FFLUSH)
+
+
+/**
+ * @}
+ */
+
+/* Private struct -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup CRYP_Private_Functions_prototypes
+ * @{
+ */
+
+static void CRYP_SetDMAConfig(CRYP_HandleTypeDef *hcryp, uint32_t inputaddr, uint16_t Size, uint32_t outputaddr);
+static void CRYP_DMAInCplt(DMA_HandleTypeDef *hdma);
+static void CRYP_DMAOutCplt(DMA_HandleTypeDef *hdma);
+static void CRYP_DMAError(DMA_HandleTypeDef *hdma);
+static void CRYP_SetKey(CRYP_HandleTypeDef *hcryp, uint32_t KeySize);
+static void CRYP_AES_IT(CRYP_HandleTypeDef *hcryp);
+static HAL_StatusTypeDef CRYP_GCMCCM_SetHeaderPhase(CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+static void CRYP_GCMCCM_SetPayloadPhase_IT(CRYP_HandleTypeDef *hcryp);
+static void CRYP_GCMCCM_SetHeaderPhase_IT(CRYP_HandleTypeDef *hcryp);
+static HAL_StatusTypeDef CRYP_GCMCCM_SetHeaderPhase_DMA(CRYP_HandleTypeDef *hcryp);
+#if !defined (CRYP_VER_2_2)
+static void CRYP_Workaround(CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+#endif /*End of not defined CRYP_VER_2_2*/
+static HAL_StatusTypeDef CRYP_AESGCM_Process_DMA(CRYP_HandleTypeDef *hcryp);
+static HAL_StatusTypeDef CRYP_AESGCM_Process_IT(CRYP_HandleTypeDef *hcryp);
+static HAL_StatusTypeDef CRYP_AESGCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+static HAL_StatusTypeDef CRYP_AESCCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+static HAL_StatusTypeDef CRYP_AESCCM_Process_IT(CRYP_HandleTypeDef *hcryp);
+static HAL_StatusTypeDef CRYP_AESCCM_Process_DMA(CRYP_HandleTypeDef *hcryp);
+static void CRYP_AES_ProcessData(CRYP_HandleTypeDef *hcrypt, uint32_t Timeout);
+static HAL_StatusTypeDef CRYP_AES_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+static HAL_StatusTypeDef CRYP_AES_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+static HAL_StatusTypeDef CRYP_AES_Decrypt_IT(CRYP_HandleTypeDef *hcryp);
+static HAL_StatusTypeDef CRYP_AES_Encrypt_IT(CRYP_HandleTypeDef *hcryp);
+static HAL_StatusTypeDef CRYP_AES_Decrypt_DMA(CRYP_HandleTypeDef *hcryp);
+static void CRYP_TDES_IT(CRYP_HandleTypeDef *hcryp);
+static HAL_StatusTypeDef CRYP_WaitOnIFEMFlag(const CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+static HAL_StatusTypeDef CRYP_WaitOnBUSYFlag(const CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+static HAL_StatusTypeDef CRYP_WaitOnOFNEFlag(const CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+static HAL_StatusTypeDef CRYP_TDES_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout);
+
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+
+/** @defgroup CRYP_Exported_Functions CRYP Exported Functions
+ * @{
+ */
+
+
+/** @defgroup CRYP_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief CRYP Initialization and Configuration functions.
+ *
+@verbatim
+ ========================================================================================
+ ##### Initialization, de-initialization and Set and Get configuration functions #####
+ ========================================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the CRYP
+ (+) DeInitialize the CRYP
+ (+) Initialize the CRYP MSP
+ (+) DeInitialize the CRYP MSP
+ (+) configure CRYP (HAL_CRYP_SetConfig) with the specified parameters in the CRYP_ConfigTypeDef
+ Parameters which are configured in This section are :
+ (++) Key size
+ (++) Data Type : 32,16, 8 or 1bit
+ (++) AlgoMode : for CRYP1 IP
+ ECB and CBC in DES/TDES Standard
+ ECB,CBC,CTR,GCM/GMAC and CCM in AES Standard.
+ (+) Get CRYP configuration (HAL_CRYP_GetConfig) from the specified parameters in the CRYP_HandleTypeDef
+
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Initializes the CRYP according to the specified
+ * parameters in the CRYP_ConfigTypeDef and creates the associated handle.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_Init(CRYP_HandleTypeDef *hcryp)
+{
+ /* Check the CRYP handle allocation */
+ if (hcryp == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check parameters */
+ assert_param(IS_CRYP_KEYSIZE(hcryp->Init.KeySize));
+ assert_param(IS_CRYP_DATATYPE(hcryp->Init.DataType));
+ assert_param(IS_CRYP_ALGORITHM(hcryp->Init.Algorithm));
+ assert_param(IS_CRYP_INIT(hcryp->Init.KeyIVConfigSkip));
+
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ if (hcryp->State == HAL_CRYP_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hcryp->Lock = HAL_UNLOCKED;
+
+ hcryp->InCpltCallback = HAL_CRYP_InCpltCallback; /* Legacy weak InCpltCallback */
+ hcryp->OutCpltCallback = HAL_CRYP_OutCpltCallback; /* Legacy weak OutCpltCallback */
+ hcryp->ErrorCallback = HAL_CRYP_ErrorCallback; /* Legacy weak ErrorCallback */
+
+ if (hcryp->MspInitCallback == NULL)
+ {
+ hcryp->MspInitCallback = HAL_CRYP_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware */
+ hcryp->MspInitCallback(hcryp);
+ }
+#else
+ if (hcryp->State == HAL_CRYP_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hcryp->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware */
+ HAL_CRYP_MspInit(hcryp);
+ }
+#endif /* (USE_HAL_CRYP_REGISTER_CALLBACKS) */
+
+ /* Set the key size(This bit field is ‘don’t care’ in the DES or TDES modes) data type and Algorithm */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_DATATYPE | CRYP_CR_KEYSIZE | CRYP_CR_ALGOMODE,
+ hcryp->Init.DataType | hcryp->Init.KeySize | hcryp->Init.Algorithm);
+#if !defined (CRYP_VER_2_2)
+ /* Read Device ID to indicate CRYP1 IP Version */
+ hcryp->Version = HAL_GetREVID();
+#endif /*End of not defined CRYP_VER_2_2*/
+ /* Reset Error Code field */
+ hcryp->ErrorCode = HAL_CRYP_ERROR_NONE;
+
+ /* Reset peripheral Key and IV configuration flag */
+ hcryp->KeyIVConfig = 0U;
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Set the default CRYP phase */
+ hcryp->Phase = CRYP_PHASE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief De-Initializes the CRYP peripheral.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_DeInit(CRYP_HandleTypeDef *hcryp)
+{
+ /* Check the CRYP handle allocation */
+ if (hcryp == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the default CRYP phase */
+ hcryp->Phase = CRYP_PHASE_READY;
+
+ /* Reset CrypInCount and CrypOutCount */
+ hcryp->CrypInCount = 0;
+ hcryp->CrypOutCount = 0;
+ hcryp->CrypHeaderCount = 0;
+
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ if (hcryp->MspDeInitCallback == NULL)
+ {
+ hcryp->MspDeInitCallback = HAL_CRYP_MspDeInit; /* Legacy weak MspDeInit */
+ }
+ /* DeInit the low level hardware */
+ hcryp->MspDeInitCallback(hcryp);
+
+#else
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ HAL_CRYP_MspDeInit(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hcryp);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the CRYP according to the specified
+ * parameters in the CRYP_ConfigTypeDef
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure
+ * @param pConf: pointer to a CRYP_ConfigTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_SetConfig(CRYP_HandleTypeDef *hcryp, CRYP_ConfigTypeDef *pConf)
+{
+ /* Check the CRYP handle allocation */
+ if ((hcryp == NULL) || (pConf == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check parameters */
+ assert_param(IS_CRYP_KEYSIZE(pConf->KeySize));
+ assert_param(IS_CRYP_DATATYPE(pConf->DataType));
+ assert_param(IS_CRYP_ALGORITHM(pConf->Algorithm));
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Set CRYP parameters */
+ hcryp->Init.DataType = pConf->DataType;
+ hcryp->Init.pKey = pConf->pKey;
+ hcryp->Init.Algorithm = pConf->Algorithm;
+ hcryp->Init.KeySize = pConf->KeySize;
+ hcryp->Init.pInitVect = pConf->pInitVect;
+ hcryp->Init.Header = pConf->Header;
+ hcryp->Init.HeaderSize = pConf->HeaderSize;
+ hcryp->Init.B0 = pConf->B0;
+ hcryp->Init.DataWidthUnit = pConf->DataWidthUnit;
+
+ /* Set the key size(This bit field is ‘don’t care’ in the DES or TDES modes) data type, AlgoMode and operating mode*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_DATATYPE | CRYP_CR_KEYSIZE | CRYP_CR_ALGOMODE,
+ hcryp->Init.DataType | hcryp->Init.KeySize | hcryp->Init.Algorithm);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Reset Error Code field */
+ hcryp->ErrorCode = HAL_CRYP_ERROR_NONE;
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Set the default CRYP phase */
+ hcryp->Phase = CRYP_PHASE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get CRYP Configuration parameters in associated handle.
+ * @param pConf: pointer to a CRYP_ConfigTypeDef structure
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_GetConfig(CRYP_HandleTypeDef *hcryp, CRYP_ConfigTypeDef *pConf)
+{
+ /* Check the CRYP handle allocation */
+ if ((hcryp == NULL) || (pConf == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Get CRYP parameters */
+ pConf->DataType = hcryp->Init.DataType;
+ pConf->pKey = hcryp->Init.pKey;
+ pConf->Algorithm = hcryp->Init.Algorithm;
+ pConf->KeySize = hcryp->Init.KeySize ;
+ pConf->pInitVect = hcryp->Init.pInitVect;
+ pConf->Header = hcryp->Init.Header ;
+ pConf->HeaderSize = hcryp->Init.HeaderSize;
+ pConf->B0 = hcryp->Init.B0;
+ pConf->DataWidthUnit = hcryp->Init.DataWidthUnit;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+}
+/**
+ * @brief Initializes the CRYP MSP.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval None
+ */
+__weak void HAL_CRYP_MspInit(CRYP_HandleTypeDef *hcryp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcryp);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_CRYP_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes CRYP MSP.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval None
+ */
+__weak void HAL_CRYP_MspDeInit(CRYP_HandleTypeDef *hcryp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcryp);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_CRYP_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User CRYP Callback
+ * To be used instead of the weak predefined callback
+ * @param hcryp cryp handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_CRYP_INPUT_COMPLETE_CB_ID Input FIFO transfer completed callback ID
+ * @arg @ref HAL_CRYP_OUTPUT_COMPLETE_CB_ID Output FIFO transfer completed callback ID
+ * @arg @ref HAL_CRYP_ERROR_CB_ID Rx Half Error callback ID
+ * @arg @ref HAL_CRYP_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_CRYP_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_CRYP_RegisterCallback(CRYP_HandleTypeDef *hcryp, HAL_CRYP_CallbackIDTypeDef CallbackID,
+ pCRYP_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_CRYP_INPUT_COMPLETE_CB_ID :
+ hcryp->InCpltCallback = pCallback;
+ break;
+
+ case HAL_CRYP_OUTPUT_COMPLETE_CB_ID :
+ hcryp->OutCpltCallback = pCallback;
+ break;
+
+ case HAL_CRYP_ERROR_CB_ID :
+ hcryp->ErrorCallback = pCallback;
+ break;
+
+ case HAL_CRYP_MSPINIT_CB_ID :
+ hcryp->MspInitCallback = pCallback;
+ break;
+
+ case HAL_CRYP_MSPDEINIT_CB_ID :
+ hcryp->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hcryp->State == HAL_CRYP_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_CRYP_MSPINIT_CB_ID :
+ hcryp->MspInitCallback = pCallback;
+ break;
+
+ case HAL_CRYP_MSPDEINIT_CB_ID :
+ hcryp->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hcryp);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an CRYP Callback
+ * CRYP callabck is redirected to the weak predefined callback
+ * @param hcryp cryp handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_CRYP_INPUT_COMPLETE_CB_ID Input FIFO transfer completed callback ID
+ * @arg @ref HAL_CRYP_OUTPUT_COMPLETE_CB_ID Output FIFO transfer completed callback ID
+ * @arg @ref HAL_CRYP_ERROR_CB_ID Rx Half Error callback ID
+ * @arg @ref HAL_CRYP_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_CRYP_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_CRYP_UnRegisterCallback(CRYP_HandleTypeDef *hcryp, HAL_CRYP_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_CRYP_INPUT_COMPLETE_CB_ID :
+ hcryp->InCpltCallback = HAL_CRYP_InCpltCallback; /* Legacy weak InCpltCallback */
+ break;
+
+ case HAL_CRYP_OUTPUT_COMPLETE_CB_ID :
+ hcryp->OutCpltCallback = HAL_CRYP_OutCpltCallback; /* Legacy weak OutCpltCallback */
+ break;
+
+ case HAL_CRYP_ERROR_CB_ID :
+ hcryp->ErrorCallback = HAL_CRYP_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_CRYP_MSPINIT_CB_ID :
+ hcryp->MspInitCallback = HAL_CRYP_MspInit;
+ break;
+
+ case HAL_CRYP_MSPDEINIT_CB_ID :
+ hcryp->MspDeInitCallback = HAL_CRYP_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hcryp->State == HAL_CRYP_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_CRYP_MSPINIT_CB_ID :
+ hcryp->MspInitCallback = HAL_CRYP_MspInit;
+ break;
+
+ case HAL_CRYP_MSPDEINIT_CB_ID :
+ hcryp->MspDeInitCallback = HAL_CRYP_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK;;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hcryp);
+
+ return status;
+}
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup CRYP_Exported_Functions_Group2 Encrypt Decrypt functions
+ * @brief CRYP processing functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Encrypt Decrypt functions #####
+ ==============================================================================
+ [..] This section provides API allowing to Encrypt/Decrypt Data following
+ Standard DES/TDES or AES, and Algorithm configured by the user:
+ (+) Standard DES/TDES only supported by CRYP1 IP, below list of Algorithm supported :
+ (++) Electronic Code Book(ECB)
+ (++) Cipher Block Chaining (CBC)
+ (+) Standard AES supported by CRYP1 IP , list of Algorithm supported:
+ (++) Electronic Code Book(ECB)
+ (++) Cipher Block Chaining (CBC)
+ (++) Counter mode (CTR)
+ (++) Cipher Block Chaining (CBC)
+ (++) Counter mode (CTR)
+ (++) Galois/counter mode (GCM)
+ (++) Counter with Cipher Block Chaining-Message(CCM)
+ [..] Three processing functions are available:
+ (+) Polling mode : HAL_CRYP_Encrypt & HAL_CRYP_Decrypt
+ (+) Interrupt mode : HAL_CRYP_Encrypt_IT & HAL_CRYP_Decrypt_IT
+ (+) DMA mode : HAL_CRYP_Encrypt_DMA & HAL_CRYP_Decrypt_DMA
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Encryption mode.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Input: Pointer to the input buffer (plaintext)
+ * @param Size: Length of the plaintext buffer in word.
+ * @param Output: Pointer to the output buffer(ciphertext)
+ * @param Timeout: Specify Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
+ uint32_t Timeout)
+{
+ uint32_t algo;
+ HAL_StatusTypeDef status;
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Change state Busy */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr, pCrypOutBuffPtr and Size parameters*/
+ hcryp->CrypInCount = 0U;
+ hcryp->CrypOutCount = 0U;
+ hcryp->pCrypInBuffPtr = Input;
+ hcryp->pCrypOutBuffPtr = Output;
+
+ /* Calculate Size parameter in Byte*/
+ if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD)
+ {
+ hcryp->Size = Size * 4U;
+ }
+ else
+ {
+ hcryp->Size = Size;
+ }
+
+ /* Set Encryption operating mode*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_ENCRYPT);
+
+ /* algo get algorithm selected */
+ algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE;
+
+ switch (algo)
+ {
+ case CRYP_DES_ECB:
+ case CRYP_DES_CBC:
+ case CRYP_TDES_ECB:
+ case CRYP_TDES_CBC:
+
+ /*Set Key */
+ hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey);
+ hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1);
+ if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2);
+ hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3);
+ hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4);
+ hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5);
+ }
+
+ /*Set Initialization Vector (IV)*/
+ if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ }
+
+ /* Flush FIFO */
+ HAL_CRYP_FIFO_FLUSH(hcryp);
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Statrt DES/TDES encryption process */
+ status = CRYP_TDES_Process(hcryp, Timeout);
+ break;
+
+ case CRYP_AES_ECB:
+ case CRYP_AES_CBC:
+ case CRYP_AES_CTR:
+
+ /* AES encryption */
+ status = CRYP_AES_Encrypt(hcryp, Timeout);
+ break;
+
+ case CRYP_AES_GCM:
+
+ /* AES GCM encryption */
+ status = CRYP_AESGCM_Process(hcryp, Timeout);
+ break;
+
+ case CRYP_AES_CCM:
+
+ /* AES CCM encryption */
+ status = CRYP_AESCCM_Process(hcryp, Timeout);
+ break;
+
+ default:
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED;
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Return function status */
+ return status ;
+}
+
+/**
+ * @brief Decryption mode.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Input: Pointer to the input buffer (ciphertext )
+ * @param Size: Length of the plaintext buffer in word.
+ * @param Output: Pointer to the output buffer(plaintext)
+ * @param Timeout: Specify Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
+ uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+ uint32_t algo;
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Change state Busy */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr, pCrypOutBuffPtr and Size parameters*/
+ hcryp->CrypInCount = 0U;
+ hcryp->CrypOutCount = 0U;
+ hcryp->pCrypInBuffPtr = Input;
+ hcryp->pCrypOutBuffPtr = Output;
+
+ /* Calculate Size parameter in Byte*/
+ if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD)
+ {
+ hcryp->Size = Size * 4U;
+ }
+ else
+ {
+ hcryp->Size = Size;
+ }
+
+ /* Set Decryption operating mode*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_DECRYPT);
+
+ /* algo get algorithm selected */
+ algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE;
+
+ switch (algo)
+ {
+ case CRYP_DES_ECB:
+ case CRYP_DES_CBC:
+ case CRYP_TDES_ECB:
+ case CRYP_TDES_CBC:
+
+ /*Set Key */
+ hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey);
+ hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1);
+ if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2);
+ hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3);
+ hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4);
+ hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5);
+ }
+
+ /*Set Initialization Vector (IV)*/
+ if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ }
+
+ /* Flush FIFO */
+ HAL_CRYP_FIFO_FLUSH(hcryp);
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Start DES/TDES decryption process */
+ status = CRYP_TDES_Process(hcryp, Timeout);
+
+ break;
+
+ case CRYP_AES_ECB:
+ case CRYP_AES_CBC:
+ case CRYP_AES_CTR:
+
+ /* AES decryption */
+ status = CRYP_AES_Decrypt(hcryp, Timeout);
+ break;
+
+ case CRYP_AES_GCM:
+
+ /* AES GCM decryption */
+ status = CRYP_AESGCM_Process(hcryp, Timeout) ;
+ break;
+
+ case CRYP_AES_CCM:
+
+ /* AES CCM decryption */
+ status = CRYP_AESCCM_Process(hcryp, Timeout);
+ break;
+
+ default:
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED;
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Encryption in interrupt mode.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Input: Pointer to the input buffer (plaintext)
+ * @param Size: Length of the plaintext buffer in word
+ * @param Output: Pointer to the output buffer(ciphertext)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output)
+{
+ uint32_t algo;
+ HAL_StatusTypeDef status;
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Change state Busy */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr, pCrypOutBuffPtr and Size parameters*/
+ hcryp->CrypInCount = 0U;
+ hcryp->CrypOutCount = 0U;
+ hcryp->pCrypInBuffPtr = Input;
+ hcryp->pCrypOutBuffPtr = Output;
+
+ /* Calculate Size parameter in Byte*/
+ if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD)
+ {
+ hcryp->Size = Size * 4U;
+ }
+ else
+ {
+ hcryp->Size = Size;
+ }
+
+ /* Set encryption operating mode*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_ENCRYPT);
+
+ /* algo get algorithm selected */
+ algo = (hcryp->Instance->CR & CRYP_CR_ALGOMODE);
+
+ switch (algo)
+ {
+ case CRYP_DES_ECB:
+ case CRYP_DES_CBC:
+ case CRYP_TDES_ECB:
+ case CRYP_TDES_CBC:
+
+ /*Set Key */
+ hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey);
+ hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1);
+ if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2);
+ hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3);
+ hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4);
+ hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5);
+ }
+ /* Set the Initialization Vector*/
+ if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ }
+
+ /* Flush FIFO */
+ HAL_CRYP_FIFO_FLUSH(hcryp);
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Enable interrupts */
+ __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI);
+
+ /* Enable CRYP to start DES/TDES process*/
+ __HAL_CRYP_ENABLE(hcryp);
+
+ status = HAL_OK;
+ break;
+
+ case CRYP_AES_ECB:
+ case CRYP_AES_CBC:
+ case CRYP_AES_CTR:
+
+ status = CRYP_AES_Encrypt_IT(hcryp);
+ break;
+
+ case CRYP_AES_GCM:
+
+ status = CRYP_AESGCM_Process_IT(hcryp) ;
+ break;
+
+ case CRYP_AES_CCM:
+
+ status = CRYP_AESCCM_Process_IT(hcryp);
+ break;
+
+ default:
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED;
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Return function status */
+ return status ;
+}
+
+/**
+ * @brief Decryption in itnterrupt mode.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Input: Pointer to the input buffer (ciphertext )
+ * @param Size: Length of the plaintext buffer in word.
+ * @param Output: Pointer to the output buffer(plaintext)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output)
+{
+ uint32_t algo;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Change state Busy */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr, pCrypOutBuffPtr and Size parameters*/
+ hcryp->CrypInCount = 0U;
+ hcryp->CrypOutCount = 0U;
+ hcryp->pCrypInBuffPtr = Input;
+ hcryp->pCrypOutBuffPtr = Output;
+
+ /* Calculate Size parameter in Byte*/
+ if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD)
+ {
+ hcryp->Size = Size * 4U;
+ }
+ else
+ {
+ hcryp->Size = Size;
+ }
+
+ /* Set decryption operating mode*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_DECRYPT);
+
+ /* algo get algorithm selected */
+ algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE;
+
+ switch (algo)
+ {
+ case CRYP_DES_ECB:
+ case CRYP_DES_CBC:
+ case CRYP_TDES_ECB:
+ case CRYP_TDES_CBC:
+
+ /*Set Key */
+ hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey);
+ hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1);
+ if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2);
+ hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3);
+ hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4);
+ hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5);
+ }
+
+ /* Set the Initialization Vector*/
+ if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ }
+ /* Flush FIFO */
+ HAL_CRYP_FIFO_FLUSH(hcryp);
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Enable interrupts */
+ __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI);
+
+ /* Enable CRYP and start DES/TDES process*/
+ __HAL_CRYP_ENABLE(hcryp);
+
+ break;
+
+ case CRYP_AES_ECB:
+ case CRYP_AES_CBC:
+ case CRYP_AES_CTR:
+
+ /* AES decryption */
+ status = CRYP_AES_Decrypt_IT(hcryp);
+ break;
+
+ case CRYP_AES_GCM:
+
+ /* AES GCM decryption */
+ status = CRYP_AESGCM_Process_IT(hcryp) ;
+ break;
+
+ case CRYP_AES_CCM:
+
+ /* AES CCMdecryption */
+ status = CRYP_AESCCM_Process_IT(hcryp);
+ break;
+
+ default:
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED;
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Encryption in DMA mode.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Input: Pointer to the input buffer (plaintext)
+ * @param Size: Length of the plaintext buffer in word.
+ * @param Output: Pointer to the output buffer(ciphertext)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t algo;
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Change state Busy */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr, pCrypOutBuffPtr and Size parameters*/
+ hcryp->CrypInCount = 0U;
+ hcryp->CrypOutCount = 0U;
+ hcryp->pCrypInBuffPtr = Input;
+ hcryp->pCrypOutBuffPtr = Output;
+
+ /* Calculate Size parameter in Byte*/
+ if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD)
+ {
+ hcryp->Size = Size * 4U;
+ }
+ else
+ {
+ hcryp->Size = Size;
+ }
+
+ /* Set encryption operating mode*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_ENCRYPT);
+
+ /* algo get algorithm selected */
+ algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE;
+
+ switch (algo)
+ {
+ case CRYP_DES_ECB:
+ case CRYP_DES_CBC:
+ case CRYP_TDES_ECB:
+ case CRYP_TDES_CBC:
+
+ /*Set Key */
+ hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey);
+ hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1);
+ if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2);
+ hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3);
+ hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4);
+ hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5);
+ }
+
+ /* Set the Initialization Vector*/
+ if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ }
+
+ /* Flush FIFO */
+ HAL_CRYP_FIFO_FLUSH(hcryp);
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Start DMA process transfer for DES/TDES */
+ CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (hcryp->Size / 4U), (uint32_t)(hcryp->pCrypOutBuffPtr));
+
+ break;
+
+ case CRYP_AES_ECB:
+ case CRYP_AES_CBC:
+ case CRYP_AES_CTR:
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ }
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Set the Key*/
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Set the Initialization Vector*/
+ if (hcryp->Init.Algorithm != CRYP_AES_ECB)
+ {
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1U);
+ hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2U);
+ hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3U);
+ }
+ } /* if (DoKeyIVConfig == 1U) */
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Start DMA process transfer for AES */
+ CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (hcryp->Size / 4U), (uint32_t)(hcryp->pCrypOutBuffPtr));
+ break;
+
+ case CRYP_AES_GCM:
+
+ /* AES GCM encryption */
+ status = CRYP_AESGCM_Process_DMA(hcryp) ;
+ break;
+
+ case CRYP_AES_CCM:
+
+ /* AES CCM encryption */
+ status = CRYP_AESCCM_Process_DMA(hcryp);
+ break;
+
+ default:
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED;
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Decryption in DMA mode.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Input: Pointer to the input buffer (ciphertext )
+ * @param Size: Length of the plaintext buffer in word
+ * @param Output: Pointer to the output buffer(plaintext)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output)
+{
+ uint32_t algo;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Change state Busy */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr, pCrypOutBuffPtr and Size parameters*/
+ hcryp->CrypInCount = 0U;
+ hcryp->CrypOutCount = 0U;
+ hcryp->pCrypInBuffPtr = Input;
+ hcryp->pCrypOutBuffPtr = Output;
+
+ /* Calculate Size parameter in Byte*/
+ if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD)
+ {
+ hcryp->Size = Size * 4U;
+ }
+ else
+ {
+ hcryp->Size = Size;
+ }
+
+ /* Set decryption operating mode*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_DECRYPT);
+
+ /* algo get algorithm selected */
+ algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE;
+
+ switch (algo)
+ {
+ case CRYP_DES_ECB:
+ case CRYP_DES_CBC:
+ case CRYP_TDES_ECB:
+ case CRYP_TDES_CBC:
+
+ /*Set Key */
+ hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey);
+ hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1);
+ if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2);
+ hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3);
+ hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4);
+ hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5);
+ }
+
+ /* Set the Initialization Vector*/
+ if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ }
+
+ /* Flush FIFO */
+ HAL_CRYP_FIFO_FLUSH(hcryp);
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Start DMA process transfer for DES/TDES */
+ CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (hcryp->Size / 4U), (uint32_t)(hcryp->pCrypOutBuffPtr));
+ break;
+
+ case CRYP_AES_ECB:
+ case CRYP_AES_CBC:
+ case CRYP_AES_CTR:
+
+ /* AES decryption */
+ status = CRYP_AES_Decrypt_DMA(hcryp);
+ break;
+
+ case CRYP_AES_GCM:
+
+ /* AES GCM decryption */
+ status = CRYP_AESGCM_Process_DMA(hcryp) ;
+
+ break;
+
+ case CRYP_AES_CCM:
+
+ /* AES CCM decryption */
+ status = CRYP_AESCCM_Process_DMA(hcryp);
+ break;
+
+ default:
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED;
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CRYP_Exported_Functions_Group3 CRYP IRQ handler management
+ * @brief CRYP IRQ handler.
+ *
+@verbatim
+ ==============================================================================
+ ##### CRYP IRQ handler management #####
+ ==============================================================================
+[..] This section provides CRYP IRQ handler and callback functions.
+ (+) HAL_CRYP_IRQHandler CRYP interrupt request
+ (+) HAL_CRYP_InCpltCallback input data transfer complete callback
+ (+) HAL_CRYP_OutCpltCallback output data transfer complete callback
+ (+) HAL_CRYP_ErrorCallback CRYP error callback
+ (+) HAL_CRYP_GetState return the CRYP state
+ (+) HAL_CRYP_GetError return the CRYP error code
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function handles cryptographic interrupt request.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval None
+ */
+void HAL_CRYP_IRQHandler(CRYP_HandleTypeDef *hcryp)
+{
+ uint32_t itstatus = hcryp->Instance->MISR;
+
+ if ((itstatus & (CRYP_IT_INI | CRYP_IT_OUTI)) != 0U)
+ {
+ if ((hcryp->Init.Algorithm == CRYP_DES_ECB) || (hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC))
+ {
+ CRYP_TDES_IT(hcryp); /* DES or TDES*/
+ }
+ else if ((hcryp->Init.Algorithm == CRYP_AES_ECB) || (hcryp->Init.Algorithm == CRYP_AES_CBC) || (hcryp->Init.Algorithm == CRYP_AES_CTR))
+ {
+ CRYP_AES_IT(hcryp); /*AES*/
+ }
+
+ else if ((hcryp->Init.Algorithm == CRYP_AES_GCM) || (hcryp->Init.Algorithm == CRYP_CR_ALGOMODE_AES_CCM))
+ {
+ /* if header phase */
+ if ((hcryp->Instance->CR & CRYP_PHASE_HEADER) == CRYP_PHASE_HEADER)
+ {
+ CRYP_GCMCCM_SetHeaderPhase_IT(hcryp);
+ }
+ else /* if payload phase */
+ {
+ CRYP_GCMCCM_SetPayloadPhase_IT(hcryp);
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+}
+
+/**
+ * @brief Return the CRYP error code.
+ * @param hcryp : pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for the CRYP IP
+ * @retval CRYP error code
+ */
+uint32_t HAL_CRYP_GetError(CRYP_HandleTypeDef *hcryp)
+{
+ return hcryp->ErrorCode;
+}
+
+/**
+ * @brief Returns the CRYP state.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module.
+ * @retval HAL state
+ */
+HAL_CRYP_STATETypeDef HAL_CRYP_GetState(CRYP_HandleTypeDef *hcryp)
+{
+ return hcryp->State;
+}
+
+/**
+ * @brief Input FIFO transfer completed callback.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module.
+ * @retval None
+ */
+__weak void HAL_CRYP_InCpltCallback(CRYP_HandleTypeDef *hcryp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcryp);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_CRYP_InCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Output FIFO transfer completed callback.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module.
+ * @retval None
+ */
+__weak void HAL_CRYP_OutCpltCallback(CRYP_HandleTypeDef *hcryp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcryp);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_CRYP_OutCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief CRYP error callback.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module.
+ * @retval None
+ */
+__weak void HAL_CRYP_ErrorCallback(CRYP_HandleTypeDef *hcryp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcryp);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_CRYP_ErrorCallback could be implemented in the user file
+ */
+}
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup CRYP_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Encryption in ECB/CBC Algorithm with DES/TDES standard.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Timeout: Timeout value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_TDES_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+
+ uint32_t temp; /* Temporary CrypOutBuff */
+ uint16_t incount; /* Temporary CrypInCount Value */
+ uint16_t outcount; /* Temporary CrypOutCount Value */
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ /*Start processing*/
+ while ((hcryp->CrypInCount < (hcryp->Size / 4U)) && (outcount < (hcryp->Size / 4U)))
+ {
+ /* Temporary CrypInCount Value */
+ incount = hcryp->CrypInCount;
+ /* Write plain data and get cipher data */
+ if (((hcryp->Instance->SR & CRYP_FLAG_IFNF) != 0x0U) && (incount < (hcryp->Size / 4U)))
+ {
+ /* Write the input block in the IN FIFO */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+
+ /* Wait for OFNE flag to be raised */
+ if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state & errorCode*/
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ if (((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) && (outcount < (hcryp->Size / 4U)))
+ {
+ /* Read the output block from the Output FIFO and put them in temporary Buffer then get CrypOutBuff from temporary buffer */
+ temp = hcryp->Instance->DOUT;
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = temp;
+ hcryp->CrypOutCount++;
+ temp = hcryp->Instance->DOUT;
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = temp;
+ hcryp->CrypOutCount++;
+ }
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+ }
+ /* Disable CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief CRYP block input/output data handling under interruption with DES/TDES standard.
+ * @note The function is called under interruption only, once
+ * interruptions have been enabled by CRYP_Decrypt_IT() and CRYP_Encrypt_IT().
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module.
+ * @retval HAL status
+ */
+static void CRYP_TDES_IT(CRYP_HandleTypeDef *hcryp)
+{
+ uint32_t temp; /* Temporary CrypOutBuff */
+
+ if (hcryp->State == HAL_CRYP_STATE_BUSY)
+ {
+ if (__HAL_CRYP_GET_IT(hcryp, CRYP_IT_INI) != 0x0U)
+ {
+ if(__HAL_CRYP_GET_FLAG(hcryp, CRYP_FLAG_INRIS) != 0x0U)
+ {
+ /* Write input block in the IN FIFO */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+
+ if (hcryp->CrypInCount == (hcryp->Size / 4U))
+ {
+ /* Disable interruption */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI);
+
+ /* Call the input data transfer complete callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered Input complete callback*/
+ hcryp->InCpltCallback(hcryp);
+#else
+ /*Call legacy weak Input complete callback*/
+ HAL_CRYP_InCpltCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ }
+ }
+
+ if (__HAL_CRYP_GET_IT(hcryp, CRYP_IT_OUTI) != 0x0U)
+ {
+ if(__HAL_CRYP_GET_FLAG(hcryp, CRYP_FLAG_OUTRIS) != 0x0U)
+ {
+ /* Read the output block from the Output FIFO and put them in temporary Buffer then get CrypOutBuff from temporary buffer */
+ temp = hcryp->Instance->DOUT;
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = temp;
+ hcryp->CrypOutCount++;
+ temp = hcryp->Instance->DOUT;
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = temp;
+ hcryp->CrypOutCount++;
+ if (hcryp->CrypOutCount == (hcryp->Size / 4U))
+ {
+ /* Disable interruption */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_OUTI);
+
+ /* Disable CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Call output transfer complete callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered Output complete callback*/
+ hcryp->OutCpltCallback(hcryp);
+#else
+ /*Call legacy weak Output complete callback*/
+ HAL_CRYP_OutCpltCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Encryption in ECB/CBC & CTR Algorithm with AES Standard
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure
+ * @param Timeout: specify Timeout value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AES_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+ uint16_t outcount; /* Temporary CrypOutCount Value */
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ }
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Set the Key*/
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ if (hcryp->Init.Algorithm != CRYP_AES_ECB)
+ {
+ /* Set the Initialization Vector*/
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1U);
+ hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2U);
+ hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3U);
+ }
+ } /* if (DoKeyIVConfig == 1U) */
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ while ((hcryp->CrypInCount < (hcryp->Size / 4U)) && (outcount < (hcryp->Size / 4U)))
+ {
+ /* Write plain Ddta and get cipher data */
+ CRYP_AES_ProcessData(hcryp, Timeout);
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+ }
+
+ /* Disable CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Encryption in ECB/CBC & CTR mode with AES Standard using interrupt mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AES_Encrypt_IT(CRYP_HandleTypeDef *hcryp)
+{
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ }
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Set the Key*/
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ if (hcryp->Init.Algorithm != CRYP_AES_ECB)
+ {
+ /* Set the Initialization Vector*/
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1U);
+ hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2U);
+ hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3U);
+ }
+ } /* if (DoKeyIVConfig == 1U) */
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ if (hcryp->Size != 0U)
+ {
+ /* Enable interrupts */
+ __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI);
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+ }
+ else
+ {
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Decryption in ECB/CBC & CTR mode with AES Standard
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure
+ * @param Timeout: Specify Timeout value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AES_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+ uint16_t outcount; /* Temporary CrypOutCount Value */
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ }
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Key preparation for ECB/CBC */
+ if (hcryp->Init.Algorithm != CRYP_AES_CTR) /*ECB or CBC*/
+ {
+ /* change ALGOMODE to key preparation for decryption*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_CR_ALGOMODE_AES_KEY);
+
+ /* Set the Key*/
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Wait for BUSY flag to be raised */
+ if (CRYP_WaitOnBUSYFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ /* Turn back to ALGOMODE of the configuration */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, hcryp->Init.Algorithm);
+ }
+ else /*Algorithm CTR */
+ {
+ /* Set the Key*/
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+ }
+
+ /* Set IV */
+ if (hcryp->Init.Algorithm != CRYP_AES_ECB)
+ {
+ /* Set the Initialization Vector*/
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2);
+ hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3);
+ }
+} /* if (DoKeyIVConfig == 1U) */
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ while ((hcryp->CrypInCount < (hcryp->Size / 4U)) && (outcount < (hcryp->Size / 4U)))
+ {
+ /* Write plain data and get cipher data */
+ CRYP_AES_ProcessData(hcryp, Timeout);
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+ }
+
+ /* Disable CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+/**
+ * @brief Decryption in ECB/CBC & CTR mode with AES Standard using interrupt mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AES_Decrypt_IT(CRYP_HandleTypeDef *hcryp)
+{
+ __IO uint32_t count = 0U;
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ }
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Key preparation for ECB/CBC */
+ if (hcryp->Init.Algorithm != CRYP_AES_CTR)
+ {
+ /* change ALGOMODE to key preparation for decryption*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_CR_ALGOMODE_AES_KEY);
+
+ /* Set the Key*/
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Wait for BUSY flag to be raised */
+ count = CRYP_TIMEOUT_KEYPREPARATION;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while (HAL_IS_BIT_SET(hcryp->Instance->SR, CRYP_FLAG_BUSY));
+
+ /* Turn back to ALGOMODE of the configuration */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, hcryp->Init.Algorithm);
+ }
+ else /*Algorithm CTR */
+ {
+ /* Set the Key*/
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+ }
+
+ /* Set IV */
+ if (hcryp->Init.Algorithm != CRYP_AES_ECB)
+ {
+ /* Set the Initialization Vector*/
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2);
+ hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3);
+ }
+} /* if (DoKeyIVConfig == 1U) */
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+ if (hcryp->Size != 0U)
+ {
+ /* Enable interrupts */
+ __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI);
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+ }
+ else
+ {
+ /* Process locked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+/**
+ * @brief Decryption in ECB/CBC & CTR mode with AES Standard using DMA mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AES_Decrypt_DMA(CRYP_HandleTypeDef *hcryp)
+{
+ __IO uint32_t count = 0U;
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ }
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Key preparation for ECB/CBC */
+ if (hcryp->Init.Algorithm != CRYP_AES_CTR)
+ {
+ /* change ALGOMODE to key preparation for decryption*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_CR_ALGOMODE_AES_KEY);
+
+ /* Set the Key*/
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Wait for BUSY flag to be raised */
+ count = CRYP_TIMEOUT_KEYPREPARATION;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while (HAL_IS_BIT_SET(hcryp->Instance->SR, CRYP_FLAG_BUSY));
+
+ /* Turn back to ALGOMODE of the configuration */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, hcryp->Init.Algorithm);
+ }
+ else /*Algorithm CTR */
+ {
+ /* Set the Key*/
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+ }
+
+ if (hcryp->Init.Algorithm != CRYP_AES_ECB)
+ {
+ /* Set the Initialization Vector*/
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2);
+ hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3);
+ }
+} /* if (DoKeyIVConfig == 1U) */
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ if (hcryp->Size != 0U)
+ {
+ /* Set the input and output addresses and start DMA transfer */
+ CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (hcryp->Size / 4U), (uint32_t)(hcryp->pCrypOutBuffPtr));
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief DMA CRYP input data process complete callback.
+ * @param hdma: DMA handle
+ * @retval None
+ */
+static void CRYP_DMAInCplt(DMA_HandleTypeDef *hdma)
+{
+ CRYP_HandleTypeDef *hcryp = (CRYP_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Disable the DMA transfer for input FIFO request by resetting the DIEN bit
+ in the DMACR register */
+ hcryp->Instance->DMACR &= (uint32_t)(~CRYP_DMACR_DIEN);
+
+ /* Call input data transfer complete callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered Input complete callback*/
+ hcryp->InCpltCallback(hcryp);
+#else
+ /*Call legacy weak Input complete callback*/
+ HAL_CRYP_InCpltCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA CRYP output data process complete callback.
+ * @param hdma: DMA handle
+ * @retval None
+ */
+static void CRYP_DMAOutCplt(DMA_HandleTypeDef *hdma)
+{
+ uint32_t count;
+ uint32_t npblb;
+ uint32_t lastwordsize;
+ uint32_t temp; /* Temporary CrypOutBuff */
+ uint32_t temp_cr_algodir;
+ CRYP_HandleTypeDef *hcryp = (CRYP_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+
+ /* Disable the DMA transfer for output FIFO */
+ hcryp->Instance->DMACR &= (uint32_t)(~CRYP_DMACR_DOEN);
+
+ /* Last block transfer in case of GCM or CCM with Size not %16*/
+ if (((hcryp->Size) % 16U) != 0U)
+ {
+ /* set CrypInCount and CrypOutCount to exact number of word already computed via DMA */
+ hcryp->CrypInCount = (hcryp->Size / 16U) * 4U ;
+ hcryp->CrypOutCount = hcryp->CrypInCount;
+
+ /* Compute the number of padding bytes in last block of payload */
+ npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size);
+
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Case of AES GCM payload encryption or AES CCM payload decryption to get right tag */
+ temp_cr_algodir = hcryp->Instance->CR & CRYP_CR_ALGODIR;
+ if (((temp_cr_algodir == CRYP_OPERATINGMODE_ENCRYPT) && (hcryp->Init.Algorithm == CRYP_AES_GCM)) ||
+ ((temp_cr_algodir == CRYP_OPERATINGMODE_DECRYPT) && (hcryp->Init.Algorithm == CRYP_AES_CCM)))
+ {
+ /* Disable the CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Specify the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, npblb << 20);
+
+ /* Enable CRYP to start the final phase */
+ __HAL_CRYP_ENABLE(hcryp);
+ }
+ }
+
+ /* Number of valid words (lastwordsize) in last block */
+ if ((npblb % 4U) == 0U)
+ {
+ lastwordsize = (16U - npblb) / 4U;
+ }
+ else
+ {
+ lastwordsize = ((16U - npblb) / 4U) + 1U;
+ }
+ /* Write the last input block in the IN FIFO */
+ for (count = 0U; count < lastwordsize; count ++)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+ /* Pad the data with zeros to have a complete block */
+ while (count < 4U)
+ {
+ hcryp->Instance->DIN = 0U;
+ count++;
+ }
+ /* Wait for OFNE flag to be raised */
+ count = CRYP_TIMEOUT_GCMCCMHEADERPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ } while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE));
+
+ /*Read the output block from the output FIFO */
+ for (count = 0U; count < 4U; count++)
+ {
+ /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */
+ temp = hcryp->Instance->DOUT;
+
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = temp;
+ hcryp->CrypOutCount++;
+ }
+ } /*End of last block transfer in case of GCM or CCM */
+
+ if ((hcryp->Init.Algorithm & CRYP_AES_GCM) != CRYP_AES_GCM)
+ {
+ /* Disable CRYP (not allowed in GCM)*/
+ __HAL_CRYP_DISABLE(hcryp);
+ }
+
+ /* Change the CRYP state to ready */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Call output data transfer complete callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered Output complete callback*/
+ hcryp->OutCpltCallback(hcryp);
+#else
+ /*Call legacy weak Output complete callback*/
+ HAL_CRYP_OutCpltCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA CRYP communication error callback.
+ * @param hdma: DMA handle
+ * @retval None
+ */
+static void CRYP_DMAError(DMA_HandleTypeDef *hdma)
+{
+ CRYP_HandleTypeDef *hcryp = (CRYP_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* DMA error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_DMA;
+
+ /* Call error callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief Set the DMA configuration and start the DMA transfer
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param inputaddr: address of the input buffer
+ * @param Size: size of the input buffer, must be a multiple of 16.
+ * @param outputaddr: address of the output buffer
+ * @retval None
+ */
+static void CRYP_SetDMAConfig(CRYP_HandleTypeDef *hcryp, uint32_t inputaddr, uint16_t Size, uint32_t outputaddr)
+{
+ /* Set the CRYP DMA transfer complete callback */
+ hcryp->hdmain->XferCpltCallback = CRYP_DMAInCplt;
+
+ /* Set the DMA input error callback */
+ hcryp->hdmain->XferErrorCallback = CRYP_DMAError;
+
+ /* Set the CRYP DMA transfer complete callback */
+ hcryp->hdmaout->XferCpltCallback = CRYP_DMAOutCplt;
+
+ /* Set the DMA output error callback */
+ hcryp->hdmaout->XferErrorCallback = CRYP_DMAError;
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Enable the input DMA Stream */
+ if (HAL_DMA_Start_IT(hcryp->hdmain, inputaddr, (uint32_t)&hcryp->Instance->DIN, Size) != HAL_OK)
+ {
+ /* DMA error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_DMA;
+
+ /* Call error callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+
+ /* Enable the output DMA Stream */
+ if (HAL_DMA_Start_IT(hcryp->hdmaout, (uint32_t)&hcryp->Instance->DOUT, outputaddr, Size) != HAL_OK)
+ {
+ /* DMA error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_DMA;
+
+ /* Call error callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ /* Enable In/Out DMA request */
+ hcryp->Instance->DMACR = CRYP_DMACR_DOEN | CRYP_DMACR_DIEN;
+}
+
+/**
+ * @brief Process Data: Write Input data in polling mode and used in AES functions.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Timeout: Specify Timeout value
+ * @retval None
+ */
+static void CRYP_AES_ProcessData(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+
+ uint32_t temp[4]; /* Temporary CrypOutBuff */
+ uint16_t incount; /* Temporary CrypInCount Value */
+ uint16_t outcount; /* Temporary CrypOutCount Value */
+ uint32_t i;
+
+ /*Temporary CrypOutCount Value*/
+ incount = hcryp->CrypInCount;
+
+ if (((hcryp->Instance->SR & CRYP_FLAG_IFNF) != 0x0U) && (incount < ((hcryp->Size) / 4U)))
+ {
+ /* Write the input block in the IN FIFO */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+
+ /* Wait for OFNE flag to be raised */
+ if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state & error code*/
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ if (((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) && (outcount < ((hcryp->Size) / 4U)))
+ {
+ /* Read the output block from the Output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */
+ for (i = 0U; i < 4U; i++)
+ {
+ temp[i] = hcryp->Instance->DOUT;
+ }
+ i = 0U;
+ while(((hcryp->CrypOutCount < ((hcryp->Size)/4U))) && (i<4U))
+ {
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i];
+ hcryp->CrypOutCount++;
+ i++;
+ }
+ }
+}
+
+/**
+ * @brief Handle CRYP block input/output data handling under interruption.
+ * @note The function is called under interruption only, once
+ * interruptions have been enabled by HAL_CRYP_Encrypt_IT or HAL_CRYP_Decrypt_IT.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module.
+ * @retval HAL status
+ */
+static void CRYP_AES_IT(CRYP_HandleTypeDef *hcryp)
+{
+ uint32_t temp[4]; /* Temporary CrypOutBuff */
+ uint16_t incount; /* Temporary CrypInCount Value */
+ uint16_t outcount; /* Temporary CrypOutCount Value */
+ uint32_t i;
+
+ if (hcryp->State == HAL_CRYP_STATE_BUSY)
+ {
+ /*Temporary CrypOutCount Value*/
+ incount = hcryp->CrypInCount;
+
+ if (((hcryp->Instance->SR & CRYP_FLAG_IFNF) != 0x0U) && (incount < (hcryp->Size / 4U)))
+ {
+ /* Write the input block in the IN FIFO */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ if (hcryp->CrypInCount == (hcryp->Size / 4U))
+ {
+ /* Disable interrupts */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI);
+
+ /* Call the input data transfer complete callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered Input complete callback*/
+ hcryp->InCpltCallback(hcryp);
+#else
+ /*Call legacy weak Input complete callback*/
+ HAL_CRYP_InCpltCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ }
+
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ if (((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) && (outcount < (hcryp->Size / 4U)))
+ {
+ /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */
+ for (i = 0U; i < 4U; i++)
+ {
+ temp[i] = hcryp->Instance->DOUT;
+ }
+ i = 0U;
+ while(((hcryp->CrypOutCount < ((hcryp->Size)/4U))) && (i<4U))
+ {
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i];
+ hcryp->CrypOutCount++;
+ i++;
+ }
+ if (hcryp->CrypOutCount == (hcryp->Size / 4U))
+ {
+ /* Disable interrupts */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_OUTI);
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Disable CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Call output transfer complete callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered Output complete callback*/
+ hcryp->OutCpltCallback(hcryp);
+#else
+ /*Call legacy weak Output complete callback*/
+ HAL_CRYP_OutCpltCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Writes Key in Key registers.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param KeySize: Size of Key
+ * @retval None
+ */
+static void CRYP_SetKey(CRYP_HandleTypeDef *hcryp, uint32_t KeySize)
+{
+ switch (KeySize)
+ {
+ case CRYP_KEYSIZE_256B:
+ hcryp->Instance->K0LR = *(uint32_t *)(hcryp->Init.pKey);
+ hcryp->Instance->K0RR = *(uint32_t *)(hcryp->Init.pKey + 1);
+ hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey + 2);
+ hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 3);
+ hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 4);
+ hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 5);
+ hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 6);
+ hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 7);
+ break;
+ case CRYP_KEYSIZE_192B:
+ hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey);
+ hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1);
+ hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2);
+ hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3);
+ hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4);
+ hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5);
+ break;
+ case CRYP_KEYSIZE_128B:
+ hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey);
+ hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 1);
+ hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 2);
+ hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 3);
+
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief Encryption/Decryption process in AES GCM mode and prepare the authentication TAG
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AESGCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t wordsize = (uint32_t)(hcryp->Size) / 4U;
+ uint32_t npblb ;
+ uint32_t temp[4]; /* Temporary CrypOutBuff */
+ uint32_t index ;
+ uint32_t lastwordsize ;
+ uint16_t outcount; /* Temporary CrypOutCount Value */
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ hcryp->SizesSum = hcryp->Size; /* Merely store payload length */
+ }
+ }
+ else
+ {
+ hcryp->SizesSum = hcryp->Size;
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Reset CrypHeaderCount */
+ hcryp->CrypHeaderCount = 0U;
+
+ /****************************** Init phase **********************************/
+
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT);
+
+ /* Set the key */
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Set the initialization vector and the counter : Initial Counter Block (ICB)*/
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2);
+ hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3);
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /*Wait for the CRYPEN bit to be cleared*/
+ while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /************************ Header phase *************************************/
+
+ if (CRYP_GCMCCM_SetHeaderPhase(hcryp, Timeout) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /*************************Payload phase ************************************/
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Disable the CRYP peripheral */
+ __HAL_CRYP_DISABLE(hcryp);
+
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Set to 0 the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, 0U);
+ }
+
+ /* Select payload phase once the header phase is performed */
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD);
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+} /* if (DoKeyIVConfig == 1U) */
+
+ if ((hcryp->Size % 16U) != 0U)
+ {
+ /* recalculate wordsize */
+ wordsize = ((wordsize / 4U) * 4U) ;
+ }
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ /* Write input data and get output Data */
+ while ((hcryp->CrypInCount < wordsize) && (outcount < wordsize))
+ {
+ /* Write plain data and get cipher data */
+ CRYP_AES_ProcessData(hcryp, Timeout);
+
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state & error code */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ if ((hcryp->Size % 16U) != 0U)
+ {
+
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Compute the number of padding bytes in last block of payload */
+ npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size);
+
+ /* Set Npblb in case of AES GCM payload encryption to get right tag*/
+ if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_ENCRYPT)
+ {
+ /* Disable the CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Specify the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, npblb << 20);
+
+ /* Enable CRYP to start the final phase */
+ __HAL_CRYP_ENABLE(hcryp);
+ }
+ /* Number of valid words (lastwordsize) in last block */
+ if ((npblb % 4U) == 0U)
+ {
+ lastwordsize = (16U - npblb) / 4U;
+ }
+ else
+ {
+ lastwordsize = ((16U - npblb) / 4U) + 1U;
+ }
+
+ /* Write the last input block in the IN FIFO */
+ for (index = 0U; index < lastwordsize; index ++)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+
+ /* Pad the data with zeros to have a complete block */
+ while (index < 4U)
+ {
+ hcryp->Instance->DIN = 0U;
+ index++;
+ }
+
+ /* Wait for OFNE flag to be raised */
+ if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+
+ /*Read the output block from the output FIFO */
+ if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U)
+ {
+ for (index = 0U; index < 4U; index++)
+ {
+ /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */
+ temp[index] = hcryp->Instance->DOUT;
+ }
+ for (index=0; index<lastwordsize; index++)
+ {
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = temp[index];
+ hcryp->CrypOutCount++;
+ }
+ }
+ }
+#if !defined (CRYP_VER_2_2)
+ else /* Workaround to be used */
+ {
+ /* Workaround 2 for STM32H7 below rev.B To generate correct TAG only when size of the last block of
+ payload is inferior to 128 bits, in case of GCM encryption or CCM decryption*/
+ CRYP_Workaround(hcryp, Timeout);
+ } /* end of NPBLB or Workaround*/
+#endif /*End of not defined CRYP_VER_2_2*/
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Encryption/Decryption process in AES GCM mode and prepare the authentication TAG in interrupt mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AESGCM_Process_IT(CRYP_HandleTypeDef *hcryp)
+{
+ __IO uint32_t count = 0U;
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ hcryp->SizesSum = hcryp->Size; /* Merely store payload length */
+ }
+ }
+ else
+ {
+ hcryp->SizesSum = hcryp->Size;
+ }
+
+ /* Configure Key, IV and process message (header and payload) */
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Reset CrypHeaderCount */
+ hcryp->CrypHeaderCount = 0U;
+
+ /******************************* Init phase *********************************/
+
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT);
+
+ /* Set the key */
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Set the initialization vector and the counter : Initial Counter Block (ICB)*/
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2);
+ hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3);
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /*Wait for the CRYPEN bit to be cleared*/
+ count = CRYP_TIMEOUT_GCMCCMINITPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN);
+
+ /***************************** Header phase *********************************/
+
+ /* Select header phase */
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER);
+ } /* end of if (DoKeyIVConfig == 1U) */
+ /* Enable interrupts */
+ __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI);
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Encryption/Decryption process in AES GCM mode and prepare the authentication TAG using DMA
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AESGCM_Process_DMA(CRYP_HandleTypeDef *hcryp)
+{
+ __IO uint32_t count = 0U;
+ uint32_t wordsize = (uint32_t)(hcryp->Size) / 4U ;
+ uint32_t index;
+ uint32_t npblb;
+ uint32_t lastwordsize;
+ uint32_t temp[4]; /* Temporary CrypOutBuff */
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ hcryp->SizesSum = hcryp->Size; /* Merely store payload length */
+ }
+ }
+ else
+ {
+ hcryp->SizesSum = hcryp->Size;
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Reset CrypHeaderCount */
+ hcryp->CrypHeaderCount = 0U;
+
+ /*************************** Init phase ************************************/
+
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT);
+
+ /* Set the key */
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Set the initialization vector and the counter : Initial Counter Block (ICB)*/
+ hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect);
+ hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1);
+ hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2);
+ hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3);
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /*Wait for the CRYPEN bit to be cleared*/
+ count = CRYP_TIMEOUT_GCMCCMINITPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN);
+
+ /************************ Header phase *************************************/
+
+ if (CRYP_GCMCCM_SetHeaderPhase_DMA(hcryp) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /************************ Payload phase ************************************/
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Disable the CRYP peripheral */
+ __HAL_CRYP_DISABLE(hcryp);
+
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Set to 0 the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, 0U);
+ }
+
+ /* Select payload phase once the header phase is performed */
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD);
+
+} /* if (DoKeyIVConfig == 1U) */
+
+ if (hcryp->Size == 0U)
+ {
+ /* Process unLocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Change the CRYP state and phase */
+ hcryp->State = HAL_CRYP_STATE_READY;
+ }
+ else if (hcryp->Size >= 16U)
+ {
+ /* for STM32H7 below rev.B : Size should be %4 otherwise Tag will be incorrectly generated for GCM Encryption:
+ Workaround is implemented in polling mode, so if last block of payload <128bit don't use DMA mode otherwise TAG is incorrectly generated */
+
+ /*DMA transfer must not include the last block in case of Size is not %16 */
+ wordsize = wordsize - (wordsize % 4U);
+
+ /*DMA transfer */
+ CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (uint16_t)wordsize, (uint32_t)(hcryp->pCrypOutBuffPtr));
+ }
+ else /* length of input data is < 16 */
+ {
+ /* Compute the number of padding bytes in last block of payload */
+ npblb = 16U - (uint32_t)hcryp->Size;
+
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Set Npblb in case of AES GCM payload encryption to get right tag*/
+ if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_ENCRYPT)
+ {
+ /* Specify the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, npblb << 20);
+ }
+ }
+ /* Enable CRYP to start the final phase */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Number of valid words (lastwordsize) in last block */
+ if ((npblb % 4U) == 0U)
+ {
+ lastwordsize = (16U - npblb) / 4U;
+ }
+ else
+ {
+ lastwordsize = ((16U - npblb) / 4U) + 1U;
+ }
+
+ /* Write the last input block in the IN FIFO */
+ for (index = 0; index < lastwordsize; index ++)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+
+ /* Pad the data with zeros to have a complete block */
+ while (index < 4U)
+ {
+ hcryp->Instance->DIN = 0U;
+ index++;
+ }
+
+ /* Wait for OFNE flag to be raised */
+ count = CRYP_TIMEOUT_GCMCCMHEADERPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ } while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE));
+
+ /*Read the output block from the output FIFO */
+ for (index = 0U; index < 4U; index++)
+ {
+ /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */
+ temp[index] = hcryp->Instance->DOUT;
+ }
+ for (index=0; index<lastwordsize; index++)
+ {
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[index];
+ hcryp->CrypOutCount++;
+ }
+
+ /* Change the CRYP state to ready */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief AES CCM encryption/decryption processing in polling mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AESCCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t wordsize = (uint32_t)(hcryp->Size) / 4U;
+ uint32_t npblb ;
+ uint32_t lastwordsize ;
+ uint32_t temp[4] ; /* Temporary CrypOutBuff */
+ uint32_t index ;
+ uint16_t outcount; /* Temporary CrypOutCount Value */
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ hcryp->SizesSum = hcryp->Size; /* Merely store payload length */
+ }
+ }
+ else
+ {
+ hcryp->SizesSum = hcryp->Size;
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Reset CrypHeaderCount */
+ hcryp->CrypHeaderCount = 0U;
+
+ /********************** Init phase ******************************************/
+
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT);
+
+ /* Set the key */
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Set the initialization vector (IV) with CTR1 information */
+ hcryp->Instance->IV0LR = (hcryp->Init.B0[0]) & CRYP_CCM_CTR1_0;
+ hcryp->Instance->IV0RR = hcryp->Init.B0[1];
+ hcryp->Instance->IV1LR = hcryp->Init.B0[2];
+ hcryp->Instance->IV1RR = (hcryp->Init.B0[3] & CRYP_CCM_CTR1_1) | CRYP_CCM_CTR1_2;
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+#if defined (CRYP_VER_2_2)
+ {
+ /* for STM32H7 rev.B and above Write B0 packet into CRYP_DR*/
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3);
+ }
+#else
+ if (hcryp->Version >= REV_ID_B)
+ {
+ /* for STM32H7 rev.B and above Write B0 packet into CRYP_DR*/
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3);
+ }
+ else /* data has to be swapped according to the DATATYPE */
+ {
+ if (hcryp->Init.DataType == CRYP_DATATYPE_8B)
+ {
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0));
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 1));
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 2));
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 3));
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_16B)
+ {
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0), 16);
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 1), 16);
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 2), 16);
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 3), 16);
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_1B)
+ {
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0));
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 1));
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 2));
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 3));
+ }
+ else
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3);
+ }
+ }
+#endif
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /*Wait for the CRYPEN bit to be cleared*/
+ while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /************************* Header phase *************************************/
+ /* Header block(B1) : associated data length expressed in bytes concatenated
+ with Associated Data (A)*/
+
+ if (CRYP_GCMCCM_SetHeaderPhase(hcryp, Timeout) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+ /********************** Payload phase ***************************************/
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Disable the CRYP peripheral */
+ __HAL_CRYP_DISABLE(hcryp);
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Set to 0 the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, 0U);
+ }
+
+ /* Select payload phase once the header phase is performed */
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD);
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+} /* if (DoKeyIVConfig == 1U) */
+
+ if ((hcryp->Size % 16U) != 0U)
+ {
+ /* recalculate wordsize */
+ wordsize = ((wordsize / 4U) * 4U) ;
+ }
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ /* Write input data and get output data */
+ while ((hcryp->CrypInCount < wordsize) && (outcount < wordsize))
+ {
+ /* Write plain data and get cipher data */
+ CRYP_AES_ProcessData(hcryp, Timeout);
+
+ /*Temporary CrypOutCount Value*/
+ outcount = hcryp->CrypOutCount;
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ if ((hcryp->Size % 16U) != 0U)
+ {
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Compute the number of padding bytes in last block of payload */
+ npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size);
+
+ if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_DECRYPT)
+ {
+ /* Disable the CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Set Npblb in case of AES CCM payload decryption to get right tag */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, npblb << 20);
+
+ /* Enable CRYP to start the final phase */
+ __HAL_CRYP_ENABLE(hcryp);
+ }
+
+ /* Number of valid words (lastwordsize) in last block */
+ if ((npblb % 4U) == 0U)
+ {
+ lastwordsize = (16U - npblb) / 4U;
+ }
+ else
+ {
+ lastwordsize = ((16U - npblb) / 4U) + 1U;
+ }
+
+ /* Write the last input block in the IN FIFO */
+ for (index = 0U; index < lastwordsize; index ++)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+
+ /* Pad the data with zeros to have a complete block */
+ while (index < 4U)
+ {
+ hcryp->Instance->DIN = 0U;
+ index++;
+ }
+
+ /* Wait for OFNE flag to be raised */
+ if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+
+ /*Read the output block from the output FIFO */
+ if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U)
+ {
+ for (index = 0U; index < 4U; index++)
+ {
+ /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */
+ temp[index] = hcryp->Instance->DOUT;
+ }
+ for (index=0; index<lastwordsize; index++)
+ {
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[index];
+ hcryp->CrypOutCount++;
+ }
+ }
+ }
+#if !defined (CRYP_VER_2_2)
+ else /* No NPBLB, Workaround to be used */
+ {
+ /* CRYP Workaround : CRYP1 generates correct TAG during CCM decryption only when ciphertext blocks size is multiple of
+ 128 bits. If lthe size of the last block of payload is inferior to 128 bits, when CCM decryption
+ is selected, then the TAG message will be wrong.*/
+ CRYP_Workaround(hcryp, Timeout);
+ }
+#endif /*End of not defined CRYP_VER_2_2*/
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief AES CCM encryption/decryption process in interrupt mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AESCCM_Process_IT(CRYP_HandleTypeDef *hcryp)
+{
+ __IO uint32_t count = 0U;
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ hcryp->SizesSum = hcryp->Size; /* Merely store payload length */
+ }
+ }
+ else
+ {
+ hcryp->SizesSum = hcryp->Size;
+ }
+
+ /* Configure Key, IV and process message (header and payload) */
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Reset CrypHeaderCount */
+ hcryp->CrypHeaderCount = 0U;
+
+ /************ Init phase ************/
+
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT);
+
+ /* Set the key */
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Set the initialization vector (IV) with CTR1 information */
+ hcryp->Instance->IV0LR = (hcryp->Init.B0[0]) & CRYP_CCM_CTR1_0;
+ hcryp->Instance->IV0RR = hcryp->Init.B0[1];
+ hcryp->Instance->IV1LR = hcryp->Init.B0[2];
+ hcryp->Instance->IV1RR = (hcryp->Init.B0[3] & CRYP_CCM_CTR1_1) | CRYP_CCM_CTR1_2;
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /*Write the B0 packet into CRYP_DR*/
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* for STM32H7 rev.B and above data has not to be swapped */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3);
+ }
+#if !defined (CRYP_VER_2_2)
+ else /* data has to be swapped according to the DATATYPE */
+ {
+ if (hcryp->Init.DataType == CRYP_DATATYPE_8B)
+ {
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0));
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 1));
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 2));
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 3));
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_16B)
+ {
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0), 16);
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 1), 16);
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 2), 16);
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 3), 16);
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_1B)
+ {
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0));
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 1));
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 2));
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 3));
+ }
+ else
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3);
+ }
+ }
+#endif /*End of not defined CRYP_VER_2_2*/
+ /*Wait for the CRYPEN bit to be cleared*/
+ count = CRYP_TIMEOUT_GCMCCMINITPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN);
+
+ /* Select header phase */
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER);
+} /* end of if (DoKeyIVConfig == 1U) */
+ /* Enable interrupts */
+ __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI);
+
+ /* Enable CRYP */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Return function status */
+ return HAL_OK;
+}
+/**
+ * @brief AES CCM encryption/decryption process in DMA mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_AESCCM_Process_DMA(CRYP_HandleTypeDef *hcryp)
+{
+ __IO uint32_t count = 0U;
+ uint32_t wordsize = (uint32_t)(hcryp->Size) / 4U ;
+ uint32_t index;
+ uint32_t npblb;
+ uint32_t lastwordsize;
+ uint32_t temp[4]; /* Temporary CrypOutBuff */
+ uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */
+
+ if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
+ {
+ if (hcryp->KeyIVConfig == 1U)
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has already been done, skip it */
+ DoKeyIVConfig = 0U;
+ hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */
+ }
+ else
+ {
+ /* If the Key and IV configuration has to be done only once
+ and if it has not been done already, do it and set KeyIVConfig
+ to keep track it won't have to be done again next time */
+ hcryp->KeyIVConfig = 1U;
+ hcryp->SizesSum = hcryp->Size; /* Merely store payload length */
+ }
+ }
+ else
+ {
+ hcryp->SizesSum = hcryp->Size;
+ }
+
+ if (DoKeyIVConfig == 1U)
+ {
+ /* Reset CrypHeaderCount */
+ hcryp->CrypHeaderCount = 0U;
+
+ /************************** Init phase **************************************/
+
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT);
+
+ /* Set the key */
+ CRYP_SetKey(hcryp, hcryp->Init.KeySize);
+
+ /* Set the initialization vector (IV) with CTR1 information */
+ hcryp->Instance->IV0LR = (hcryp->Init.B0[0]) & CRYP_CCM_CTR1_0;
+ hcryp->Instance->IV0RR = hcryp->Init.B0[1];
+ hcryp->Instance->IV1LR = hcryp->Init.B0[2];
+ hcryp->Instance->IV1RR = (hcryp->Init.B0[3] & CRYP_CCM_CTR1_1) | CRYP_CCM_CTR1_2;
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /*Write the B0 packet into CRYP_DR*/
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* for STM32H7 rev.B and above data has not to be swapped */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3);
+ }
+#if !defined (CRYP_VER_2_2)
+ else /* data has to be swapped according to the DATATYPE */
+ {
+ if (hcryp->Init.DataType == CRYP_DATATYPE_8B)
+ {
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0));
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 1));
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 2));
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 3));
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_16B)
+ {
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0), 16);
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 1), 16);
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 2), 16);
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 3), 16);
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_1B)
+ {
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0));
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 1));
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 2));
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 3));
+ }
+ else
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2);
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3);
+ }
+ }
+#endif /*End of not defined CRYP_VER_2_2*/
+ /*Wait for the CRYPEN bit to be cleared*/
+ count = CRYP_TIMEOUT_GCMCCMINITPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN);
+
+ /********************* Header phase *****************************************/
+
+ if (CRYP_GCMCCM_SetHeaderPhase_DMA(hcryp) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /******************** Payload phase *****************************************/
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Disable the CRYP peripheral */
+ __HAL_CRYP_DISABLE(hcryp);
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Set to 0 the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, 0U);
+ }
+
+ /* Select payload phase once the header phase is performed */
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD);
+ } /* if (DoKeyIVConfig == 1U) */
+
+ if (hcryp->Size == 0U)
+ {
+ /* Process unLocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Change the CRYP state and phase */
+ hcryp->State = HAL_CRYP_STATE_READY;
+ }
+ else if (hcryp->Size >= 16U)
+ {
+ /* for STM32H7 below rev.B :: Size should be %4 otherwise Tag will be incorrectly generated for CCM Decryption, Workaround is implemented in polling mode*/
+ /*DMA transfer must not include the last block in case of Size is not %16 */
+ wordsize = wordsize - (wordsize % 4U);
+
+ /*DMA transfer */
+ CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (uint16_t) wordsize, (uint32_t)(hcryp->pCrypOutBuffPtr));
+ }
+ else /* length of input data is < 16U */
+ {
+ /* Compute the number of padding bytes in last block of payload */
+ npblb = 16U - (uint32_t)(hcryp->Size);
+
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Set Npblb in case of AES CCM payload decryption to get right tag*/
+ if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_DECRYPT)
+ {
+ /* Specify the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, npblb << 20);
+ }
+ }
+ /* Enable CRYP to start the final phase */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Number of valid words (lastwordsize) in last block */
+ if ((npblb % 4U) == 0U)
+ {
+ lastwordsize = (16U - npblb) / 4U;
+ }
+ else
+ {
+ lastwordsize = ((16U - npblb) / 4U) + 1U;
+ }
+
+ /* Write the last input block in the IN FIFO */
+ for (index = 0U; index < lastwordsize; index ++)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+
+ /* Pad the data with zeros to have a complete block */
+ while (index < 4U)
+ {
+ hcryp->Instance->DIN = 0U;
+ index++;
+ }
+
+ /* Wait for OFNE flag to be raised */
+ count = CRYP_TIMEOUT_GCMCCMHEADERPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ } while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE));
+
+ /*Read the output block from the output FIFO */
+ for (index = 0U; index < 4U; index++)
+ {
+ /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */
+ temp[index] = hcryp->Instance->DOUT;
+ }
+ for (index=0; index<lastwordsize; index++)
+ {
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[index];
+ hcryp->CrypOutCount++;
+ }
+
+ /* Change the CRYP state to ready */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets the payload phase in interrupt mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @retval state
+ */
+static void CRYP_GCMCCM_SetPayloadPhase_IT(CRYP_HandleTypeDef *hcryp)
+{
+ uint32_t loopcounter;
+ uint32_t temp[4]; /* Temporary CrypOutBuff */
+ uint32_t lastwordsize;
+ uint32_t npblb;
+ uint32_t temp_cr_algodir;
+ uint8_t negative = 0U;
+ uint32_t i;
+
+ /***************************** Payload phase *******************************/
+
+ if ((hcryp->Size / 4U) < hcryp->CrypInCount)
+ {
+ negative = 1U;
+ }
+
+ if (hcryp->Size == 0U)
+ {
+ /* Disable interrupts */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+ }
+
+ else if ((((hcryp->Size / 4U) - (hcryp->CrypInCount)) >= 4U) &&
+ (negative == 0U))
+ {
+ if ((hcryp->Instance->IMSCR & CRYP_IMSCR_INIM)!= 0x0U)
+ {
+ /* Write the input block in the IN FIFO */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ if (((hcryp->Size / 4U) == hcryp->CrypInCount) && ((hcryp->Size % 16U) == 0U))
+ {
+ /* Disable interrupts */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI);
+ /* Call the input data transfer complete callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U)
+ /*Call registered Input complete callback*/
+ hcryp->InCpltCallback(hcryp);
+#else
+ /*Call legacy weak Input complete callback*/
+ HAL_CRYP_InCpltCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+
+ if (hcryp->CrypOutCount < (hcryp->Size / 4U))
+ {
+ if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U)
+ {
+ /* Read the output block from the Output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */
+ for (i = 0U; i < 4U; i++)
+ {
+ temp[i] = hcryp->Instance->DOUT;
+ }
+ i = 0U;
+ while(((hcryp->CrypOutCount < ((hcryp->Size)/4U))) && (i<4U))
+ {
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i];
+ hcryp->CrypOutCount++;
+ i++;
+ }
+ if (((hcryp->Size / 4U) == hcryp->CrypOutCount) && ((hcryp->Size % 16U) == 0U))
+ {
+ /* Disable interrupts */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_OUTI);
+
+ /* Change the CRYP state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Disable CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Call output transfer complete callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U)
+ /*Call registered Output complete callback*/
+ hcryp->OutCpltCallback(hcryp);
+#else
+ /*Call legacy weak Output complete callback*/
+ HAL_CRYP_OutCpltCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ }
+ }
+ }
+ }
+ else if ((hcryp->Size % 16U) != 0U)
+ {
+ /* Set padding only in case of input fifo interrupt */
+ if ((hcryp->Instance->IMSCR & CRYP_IMSCR_INIM)!= 0x0U)
+ {
+ /* Compute the number of padding bytes in last block of payload */
+ npblb = ((((uint32_t)hcryp->Size / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size);
+
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Set Npblb in case of AES GCM payload encryption and CCM decryption to get right tag */
+ temp_cr_algodir = hcryp->Instance->CR & CRYP_CR_ALGODIR;
+
+ if (((temp_cr_algodir == CRYP_OPERATINGMODE_ENCRYPT) && (hcryp->Init.Algorithm == CRYP_AES_GCM)) ||
+ ((temp_cr_algodir == CRYP_OPERATINGMODE_DECRYPT) && (hcryp->Init.Algorithm == CRYP_AES_CCM)))
+ {
+ /* Disable the CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Specify the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, npblb << 20);
+
+ /* Enable CRYP to start the final phase */
+ __HAL_CRYP_ENABLE(hcryp);
+ }
+ }
+
+ /* Number of valid words (lastwordsize) in last block */
+ if ((npblb % 4U) == 0U)
+ {
+ lastwordsize = (16U - npblb) / 4U;
+ }
+ else
+ {
+ lastwordsize = ((16U - npblb) / 4U) + 1U;
+ }
+
+ /* Write the last input block in the IN FIFO */
+ for (loopcounter = 0U; loopcounter < lastwordsize; loopcounter++)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+ /* Pad the data with zeros to have a complete block */
+ while (loopcounter < 4U)
+ {
+ hcryp->Instance->DIN = 0U;
+ loopcounter++;
+ }
+
+ /* Disable the input FIFO Interrupt */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI);
+ }
+
+ /*Read the output block from the output FIFO */
+ if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U)
+ {
+ for (i = 0U; i < 4U; i++)
+ {
+ temp[i] = hcryp->Instance->DOUT;
+ }
+ if (( (hcryp->Size)/4U)==0U)
+ {
+ for (i = 0U; (uint16_t)i<((hcryp->Size)%4U); i++)
+ {
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i];
+ hcryp->CrypOutCount++;
+ }
+ }
+ i = 0U;
+ while(((hcryp->CrypOutCount < ((hcryp->Size)/4U))) && (i<4U))
+ {
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i];
+ hcryp->CrypOutCount++;
+ i++;
+ }
+ }
+
+ /* Disable the output FIFO Interrupt */
+ if (hcryp->CrypOutCount >= ((hcryp->Size) / 4U))
+ {
+ /* Disable interrupts */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_OUTI | CRYP_IT_INI);
+
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Call output transfer complete callback */
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U)
+ /*Call registered Output complete callback*/
+ hcryp->OutCpltCallback(hcryp);
+#else
+ /*Call legacy weak Output complete callback*/
+ HAL_CRYP_OutCpltCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+
+/**
+ * @brief Sets the header phase in polling mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module(Header & HeaderSize)
+ * @param Timeout: Timeout value
+ * @retval state
+ */
+static HAL_StatusTypeDef CRYP_GCMCCM_SetHeaderPhase(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+ uint32_t loopcounter;
+
+ /***************************** Header phase for GCM/GMAC or CCM *********************************/
+
+ if ((hcryp->Init.HeaderSize != 0U))
+ {
+ /* Select header phase */
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER);
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ if ((hcryp->Init.HeaderSize % 4U) == 0U)
+ {
+ /* HeaderSize %4, no padding */
+ for (loopcounter = 0U; (loopcounter < hcryp->Init.HeaderSize); loopcounter += 4U)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+
+ /* Wait for IFEM to be raised */
+ if (CRYP_WaitOnIFEMFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ }
+ else
+ {
+ /*Write header block in the IN FIFO without last block */
+ for (loopcounter = 0U; (loopcounter < ((hcryp->Init.HeaderSize) - (hcryp->Init.HeaderSize % 4U))); loopcounter += 4U)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+
+ /* Wait for IFEM to be raised */
+ if (CRYP_WaitOnIFEMFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ /* Last block optionally pad the data with zeros*/
+ for (loopcounter = 0U; (loopcounter < (hcryp->Init.HeaderSize % 4U)); loopcounter++)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ }
+ while (loopcounter < 4U)
+ {
+ /* pad the data with zeros to have a complete block */
+ hcryp->Instance->DIN = 0x0U;
+ loopcounter++;
+ }
+ /* Wait for CCF IFEM to be raised */
+ if (CRYP_WaitOnIFEMFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ /* Wait until the complete message has been processed */
+ if (CRYP_WaitOnBUSYFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked & return error */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets the header phase when using DMA in process
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module(Header & HeaderSize)
+ * @retval None
+ */
+static HAL_StatusTypeDef CRYP_GCMCCM_SetHeaderPhase_DMA(CRYP_HandleTypeDef *hcryp)
+{
+ __IO uint32_t count = 0U;
+ uint32_t loopcounter;
+
+ /***************************** Header phase for GCM/GMAC or CCM *********************************/
+ if ((hcryp->Init.HeaderSize != 0U))
+ {
+ /* Select header phase */
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER);
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ if ((hcryp->Init.HeaderSize % 4U) == 0U)
+ {
+ /* HeaderSize %4, no padding */
+ for (loopcounter = 0U; (loopcounter < hcryp->Init.HeaderSize); loopcounter += 4U)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+
+ /* Wait for IFEM to be raised */
+ count = CRYP_TIMEOUT_GCMCCMHEADERPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_IFEM));
+ }
+ }
+ else
+ {
+ /*Write header block in the IN FIFO without last block */
+ for (loopcounter = 0U; (loopcounter < ((hcryp->Init.HeaderSize) - (hcryp->Init.HeaderSize % 4U))); loopcounter += 4U)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+
+ /* Wait for IFEM to be raised */
+ count = CRYP_TIMEOUT_GCMCCMHEADERPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_IFEM));
+ }
+ /* Last block optionally pad the data with zeros*/
+ for (loopcounter = 0U; (loopcounter < (hcryp->Init.HeaderSize % 4U)); loopcounter++)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ }
+ while (loopcounter < 4U)
+ {
+ /* Pad the data with zeros to have a complete block */
+ hcryp->Instance->DIN = 0x0U;
+ loopcounter++;
+ }
+ /* Wait for IFEM to be raised */
+ count = CRYP_TIMEOUT_GCMCCMHEADERPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_IFEM));
+ }
+ /* Wait until the complete message has been processed */
+ count = CRYP_TIMEOUT_GCMCCMHEADERPHASE;
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ } while (HAL_IS_BIT_SET(hcryp->Instance->SR, CRYP_FLAG_BUSY));
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets the header phase in interrupt mode
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module(Header & HeaderSize)
+ * @retval None
+ */
+static void CRYP_GCMCCM_SetHeaderPhase_IT(CRYP_HandleTypeDef *hcryp)
+{
+ uint32_t loopcounter;
+
+ /***************************** Header phase *********************************/
+
+ if (hcryp->Init.HeaderSize == hcryp->CrypHeaderCount)
+ {
+ /* Disable interrupts */
+ __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI);
+
+ /* Disable the CRYP peripheral */
+ __HAL_CRYP_DISABLE(hcryp);
+
+#if !defined (CRYP_VER_2_2)
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ /* Set to 0 the number of non-valid bytes using NPBLB register*/
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_NPBLB, 0U);
+ }
+
+ /* Set the phase */
+ hcryp->Phase = CRYP_PHASE_PROCESS;
+
+ /* Select payload phase once the header phase is performed */
+ CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD);
+
+ /* Enable Interrupts */
+ __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI);
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+ }
+ else if (((hcryp->Init.HeaderSize) - (hcryp->CrypHeaderCount)) >= 4U)
+
+ {
+ /* HeaderSize %4, no padding */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ }
+ else
+ {
+ /* Last block optionally pad the data with zeros*/
+ for (loopcounter = 0U; loopcounter < (hcryp->Init.HeaderSize % 4U); loopcounter++)
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
+ hcryp->CrypHeaderCount++ ;
+ }
+ while (loopcounter < 4U)
+ {
+ /* Pad the data with zeros to have a complete block */
+ hcryp->Instance->DIN = 0x0U;
+ loopcounter++;
+ }
+ }
+}
+
+#if !defined (CRYP_VER_2_2)
+/**
+ * @brief Workaround used for GCM/CCM mode.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param Timeout: Timeout value
+ * @retval None
+ */
+static void CRYP_Workaround(CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+ uint32_t iv1temp;
+ uint32_t temp[4] = {0};
+ uint32_t temp2[4] = {0};
+ uint32_t intermediate_data[4] = {0};
+ uint32_t index;
+ uint32_t lastwordsize;
+ uint32_t npblb;
+
+ /* Compute the number of padding bytes in last block of payload */
+ npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size);
+
+ /* Number of valid words (lastwordsize) in last block */
+ if ((npblb % 4U) == 0U)
+ {
+ lastwordsize = (16U - npblb) / 4U;
+ }
+ else
+ {
+ lastwordsize = ((16U - npblb) / 4U) + 1U;
+ }
+
+ /* Workaround 2, case GCM encryption */
+ if (hcryp->Init.Algorithm == CRYP_AES_GCM)
+ {
+ if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_ENCRYPT)
+ {
+ /*Workaround in order to properly compute authentication tags while doing
+ a GCM encryption with the last block of payload size inferior to 128 bits*/
+ /* Disable CRYP to start the final phase */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /*Update CRYP_IV1R register and ALGOMODE*/
+ hcryp->Instance->IV1RR = ((hcryp->Instance->CSGCMCCM7R)-1U);
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_AES_CTR);
+
+ /* Enable CRYP to start the final phase */
+ __HAL_CRYP_ENABLE(hcryp);
+ }
+
+ for (index = 0; index < lastwordsize ; index ++)
+ {
+ /* Write the last input block in the IN FIFO */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+ while (index < 4U)
+ {
+ /* Pad the data with zeros to have a complete block */
+ hcryp->Instance->DIN = 0U;
+ index++;
+ }
+ /* Wait for OFNE flag to be raised */
+ if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U)
+ {
+ for (index = 0U; index < 4U; index++)
+ {
+ /* Read the output block from the output FIFO */
+ intermediate_data[index] = hcryp->Instance->DOUT;
+
+ /* Intermediate data buffer to be used in for the workaround*/
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = intermediate_data[index];
+ hcryp->CrypOutCount++;
+ }
+ }
+
+ if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_ENCRYPT)
+ {
+ /*workaround in order to properly compute authentication tags while doing
+ a GCM encryption with the last block of payload size inferior to 128 bits*/
+ /* Change the AES mode to GCM mode and Select Final phase */
+ /* configured CHMOD GCM */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_AES_GCM);
+
+ /* configured final phase */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH, CRYP_PHASE_FINAL);
+
+ if ( (hcryp->Instance->CR & CRYP_CR_DATATYPE) == CRYP_DATATYPE_32B)
+ {
+ if ((npblb %4U)==1U)
+ {
+ intermediate_data[lastwordsize-1U] &= 0xFFFFFF00U;
+ }
+ if ((npblb %4U)==2U)
+ {
+ intermediate_data[lastwordsize-1U] &= 0xFFFF0000U;
+ }
+ if ((npblb %4U)==3U)
+ {
+ intermediate_data[lastwordsize-1U] &= 0xFF000000U;
+ }
+ }
+ else if ((hcryp->Instance->CR & CRYP_CR_DATATYPE) == CRYP_DATATYPE_8B)
+ {
+ if ((npblb %4U)==1U)
+ {
+ intermediate_data[lastwordsize-1U] &= __REV(0xFFFFFF00U);
+ }
+ if ((npblb %4U)==2U)
+ {
+ intermediate_data[lastwordsize-1U] &= __REV(0xFFFF0000U);
+ }
+ if ((npblb %4U)==3U)
+ {
+ intermediate_data[lastwordsize-1U] &= __REV(0xFF000000U);
+ }
+ }
+ else if ((hcryp->Instance->CR & CRYP_CR_DATATYPE) == CRYP_DATATYPE_16B)
+ {
+ if ((npblb %4U)==1U)
+ {
+ intermediate_data[lastwordsize-1U] &= __ROR((0xFFFFFF00U), 16);
+ }
+ if ((npblb %4U)==2U)
+ {
+ intermediate_data[lastwordsize-1U] &= __ROR((0xFFFF0000U), 16);
+ }
+ if ((npblb %4U)==3U)
+ {
+ intermediate_data[lastwordsize-1U] &= __ROR((0xFF000000U), 16);
+ }
+ }
+ else /*CRYP_DATATYPE_1B*/
+ {
+ if ((npblb %4U)==1U)
+ {
+ intermediate_data[lastwordsize-1U] &= __RBIT(0xFFFFFF00U);
+ }
+ if ((npblb %4U)==2U)
+ {
+ intermediate_data[lastwordsize-1U] &= __RBIT(0xFFFF0000U);
+ }
+ if ((npblb %4U)==3U)
+ {
+ intermediate_data[lastwordsize-1U] &= __RBIT(0xFF000000U);
+ }
+ }
+
+ for (index = 0U; index < lastwordsize ; index ++)
+ {
+ /*Write the intermediate_data in the IN FIFO */
+ hcryp->Instance->DIN = intermediate_data[index];
+ }
+ while (index < 4U)
+ {
+ /* Pad the data with zeros to have a complete block */
+ hcryp->Instance->DIN = 0x0U;
+ index++;
+ }
+ /* Wait for OFNE flag to be raised */
+ if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+
+ if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U)
+ {
+ for (index = 0U; index < 4U; index++)
+ {
+ intermediate_data[index] = hcryp->Instance->DOUT;
+ }
+ }
+ }
+ } /* End of GCM encryption */
+ else
+ {
+ /* Workaround 2, case CCM decryption, in order to properly compute
+ authentication tags while doing a CCM decryption with the last block
+ of payload size inferior to 128 bits*/
+
+ if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_DECRYPT)
+ {
+ iv1temp = hcryp->Instance->CSGCMCCM7R;
+
+ /* Disable CRYP to start the final phase */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ temp[0] = hcryp->Instance->CSGCMCCM0R;
+ temp[1] = hcryp->Instance->CSGCMCCM1R;
+ temp[2] = hcryp->Instance->CSGCMCCM2R;
+ temp[3] = hcryp->Instance->CSGCMCCM3R;
+
+ hcryp->Instance->IV1RR = iv1temp;
+
+ /* Configured CHMOD CTR */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_AES_CTR);
+
+ /* Enable CRYP to start the final phase */
+ __HAL_CRYP_ENABLE(hcryp);
+ }
+ /* Last block optionally pad the data with zeros*/
+ for (index = 0U; index < lastwordsize; index ++)
+ {
+ /* Write the last Input block in the IN FIFO */
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ hcryp->CrypInCount++;
+ }
+ while (index < 4U)
+ {
+ /* Pad the data with zeros to have a complete block */
+ hcryp->Instance->DIN = 0U;
+ index++;
+ }
+ /* Wait for OFNE flag to be raised */
+ if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+
+ if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U)
+ {
+ for (index = 0U; index < 4U; index++)
+ {
+ /* Read the Output block from the Output FIFO */
+ intermediate_data[index] = hcryp->Instance->DOUT;
+
+ /*intermediate data buffer to be used in for the workaround*/
+ *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = intermediate_data[index];
+ hcryp->CrypOutCount++;
+ }
+ }
+
+ if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_DECRYPT)
+ {
+ temp2[0] = hcryp->Instance->CSGCMCCM0R;
+ temp2[1] = hcryp->Instance->CSGCMCCM1R;
+ temp2[2] = hcryp->Instance->CSGCMCCM2R;
+ temp2[3] = hcryp->Instance->CSGCMCCM3R;
+
+ /* configured CHMOD CCM */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_AES_CCM);
+
+ /* configured Header phase */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH, CRYP_PHASE_HEADER);
+
+ /*set to zero the bits corresponding to the padded bits*/
+ for (index = lastwordsize; index < 4U; index ++)
+ {
+ intermediate_data[index] = 0U;
+ }
+
+ if ((npblb % 4U) == 1U)
+ {
+ intermediate_data[lastwordsize - 1U] &= 0xFFFFFF00U;
+ }
+ if ((npblb % 4U) == 2U)
+ {
+ intermediate_data[lastwordsize - 1U] &= 0xFFFF0000U;
+ }
+ if ((npblb % 4U) == 3U)
+ {
+ intermediate_data[lastwordsize - 1U] &= 0xFF000000U;
+ }
+
+ for (index = 0U; index < 4U ; index ++)
+ {
+ intermediate_data[index] ^= temp[index];
+ intermediate_data[index] ^= temp2[index];
+ }
+ for (index = 0U; index < 4U; index ++)
+ {
+ /* Write the last Input block in the IN FIFO */
+ hcryp->Instance->DIN = intermediate_data[index] ;
+ }
+
+ /* Wait for BUSY flag to be raised */
+ if (CRYP_WaitOnBUSYFlag(hcryp, Timeout) != HAL_OK)
+ {
+ /* Disable the CRYP peripheral clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hcryp->ErrorCallback(hcryp);
+#else
+ /*Call legacy weak error callback*/
+ HAL_CRYP_ErrorCallback(hcryp);
+#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
+ }
+ }
+ } /* End of CCM WKA*/
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcryp);
+}
+#endif /*End of not defined CRYP_VER_2_2*/
+
+/**
+ * @brief Handle CRYP hardware block Timeout when waiting for IFEM flag to be raised.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_WaitOnIFEMFlag(const CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_IFEM))
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ return HAL_ERROR;
+ }
+ }
+ }
+ return HAL_OK;
+}
+/**
+ * @brief Handle CRYP hardware block Timeout when waiting for BUSY flag to be raised.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_WaitOnBUSYFlag(const CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ while (HAL_IS_BIT_SET(hcryp->Instance->SR, CRYP_FLAG_BUSY))
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ return HAL_ERROR;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Handle CRYP hardware block Timeout when waiting for OFNE flag to be raised.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CRYP_WaitOnOFNEFlag(const CRYP_HandleTypeDef *hcryp, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE))
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ return HAL_ERROR;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+
+/**
+ * @}
+ */
+
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+
+/**
+ * @}
+ */
+#endif /* CRYP */
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_cryp_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_cryp_ex.c
new file mode 100644
index 0000000000..cda921b88a
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_cryp_ex.c
@@ -0,0 +1,446 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_cryp_ex.c
+ * @author MCD Application Team
+ * @brief Extended CRYP HAL module driver
+ * This file provides firmware functions to manage the following
+ * functionalities of CRYP extension peripheral:
+ * + Extended AES processing functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The CRYP extension HAL driver can be used after AES-GCM or AES-CCM
+ Encryption/Decryption to get the authentication messages.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#if defined (CRYP)
+/** @defgroup CRYPEx CRYPEx
+ * @brief CRYP Extension HAL module driver.
+ * @{
+ */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup CRYPEx_Private_Defines
+ * @{
+ */
+
+#define CRYP_PHASE_INIT 0x00000000U
+#define CRYP_PHASE_HEADER CRYP_CR_GCM_CCMPH_0
+#define CRYP_PHASE_PAYLOAD CRYP_CR_GCM_CCMPH_1
+#define CRYP_PHASE_FINAL CRYP_CR_GCM_CCMPH
+
+#define CRYP_OPERATINGMODE_ENCRYPT 0x00000000U
+#define CRYP_OPERATINGMODE_DECRYPT CRYP_CR_ALGODIR
+
+#define CRYPEx_PHASE_PROCESS 0x02U /*!< CRYP peripheral is in processing phase */
+#define CRYPEx_PHASE_FINAL 0x03U /*!< CRYP peripheral is in final phase this is relevant only with CCM and GCM modes */
+
+/* CTR0 information to use in CCM algorithm */
+#define CRYP_CCM_CTR0_0 0x07FFFFFFU
+#define CRYP_CCM_CTR0_3 0xFFFFFF00U
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+
+
+
+/* Exported functions---------------------------------------------------------*/
+/** @addtogroup CRYPEx_Exported_Functions
+ * @{
+ */
+
+/** @defgroup CRYPEx_Exported_Functions_Group1 Extended AES processing functions
+ * @brief CRYPEx Extended processing functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Extended AES processing functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to generate the authentication
+ TAG in Polling mode
+ (+)HAL_CRYPEx_AESGCM_GenerateAuthTAG
+ (+)HAL_CRYPEx_AESCCM_GenerateAuthTAG
+ they should be used after Encrypt/Decrypt operation.
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief generate the GCM authentication TAG.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param AuthTag: Pointer to the authentication buffer
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYPEx_AESGCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint64_t headerlength = (uint64_t)(hcryp->Init.HeaderSize) * 32U; /* Header length in bits */
+ uint64_t inputlength = (uint64_t)hcryp->SizesSum * 8U; /* input length in bits */
+ uint32_t tagaddr = (uint32_t)AuthTag;
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Check if initialization phase has already been performed */
+ if (hcryp->Phase == CRYPEx_PHASE_PROCESS)
+ {
+ /* Change the CRYP phase */
+ hcryp->Phase = CRYPEx_PHASE_FINAL;
+ }
+ else /* Initialization phase has not been performed*/
+ {
+ /* Disable the Peripheral */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Sequence error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE;
+
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+
+ /* Disable CRYP to start the final phase */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Select final phase */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH, CRYP_PHASE_FINAL);
+
+ /*ALGODIR bit must be set to ‘0’.*/
+ hcryp->Instance->CR &= ~CRYP_CR_ALGODIR;
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Write the number of bits in header (64 bits) followed by the number of bits
+ in the payload */
+#if !defined (CRYP_VER_2_2)
+ /* STM32H7 rev.B and above : data has to be inserted normally (no swapping)*/
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = (uint32_t)(headerlength);
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = (uint32_t)(inputlength);
+ }
+#if !defined (CRYP_VER_2_2)
+ else/* data has to be swapped according to the DATATYPE */
+ {
+ if (hcryp->Init.DataType == CRYP_DATATYPE_1B)
+ {
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = __RBIT((uint32_t)(headerlength));
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = __RBIT((uint32_t)(inputlength));
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_8B)
+ {
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = __REV((uint32_t)(headerlength));
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = __REV((uint32_t)(inputlength));
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_16B)
+ {
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = __ROR((uint32_t)headerlength, 16U);
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = __ROR((uint32_t)inputlength, 16U);
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_32B)
+ {
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = (uint32_t)(headerlength);
+ hcryp->Instance->DIN = 0U;
+ hcryp->Instance->DIN = (uint32_t)(inputlength);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+#endif /*End of not defined CRYP_VER_2_2*/
+ /* Wait for OFNE flag to be raised */
+ tickstart = HAL_GetTick();
+ while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE))
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable the CRYP Peripheral Clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Read the authentication TAG in the output FIFO */
+ *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
+ tagaddr += 4U;
+ *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
+ tagaddr += 4U;
+ *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
+ tagaddr += 4U;
+ *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
+
+ /* Disable the peripheral */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ }
+ else
+ {
+ /* Busy error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief AES CCM Authentication TAG generation.
+ * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains
+ * the configuration information for CRYP module
+ * @param AuthTag: Pointer to the authentication buffer
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CRYPEx_AESCCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout)
+{
+ uint32_t tagaddr = (uint32_t)AuthTag;
+ uint32_t ctr0 [4] = {0};
+ uint32_t ctr0addr = (uint32_t)ctr0;
+ uint32_t tickstart;
+
+ if (hcryp->State == HAL_CRYP_STATE_READY)
+ {
+ /* Process locked */
+ __HAL_LOCK(hcryp);
+
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_BUSY;
+
+ /* Check if initialization phase has already been performed */
+ if (hcryp->Phase == CRYPEx_PHASE_PROCESS)
+ {
+ /* Change the CRYP phase */
+ hcryp->Phase = CRYPEx_PHASE_FINAL;
+ }
+ else /* Initialization phase has not been performed*/
+ {
+ /* Disable the peripheral */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Sequence error code field */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE;
+
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+
+ /* Disable CRYP to start the final phase */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Select final phase & ALGODIR bit must be set to ‘0’. */
+ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH | CRYP_CR_ALGODIR, CRYP_PHASE_FINAL | CRYP_OPERATINGMODE_ENCRYPT);
+
+ /* Enable the CRYP peripheral */
+ __HAL_CRYP_ENABLE(hcryp);
+
+ /* Write the counter block in the IN FIFO, CTR0 information from B0
+ data has to be swapped according to the DATATYPE*/
+ ctr0[0] = (hcryp->Init.B0[0]) & CRYP_CCM_CTR0_0;
+ ctr0[1] = hcryp->Init.B0[1];
+ ctr0[2] = hcryp->Init.B0[2];
+ ctr0[3] = hcryp->Init.B0[3] & CRYP_CCM_CTR0_3;
+
+#if !defined (CRYP_VER_2_2)
+ /*STM32H7 rev.B and above : data has to be inserted normally (no swapping)*/
+ if (hcryp->Version >= REV_ID_B)
+#endif /*End of not defined CRYP_VER_2_2*/
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
+ }
+#if !defined (CRYP_VER_2_2)
+ else /* data has to be swapped according to the DATATYPE */
+ {
+ if (hcryp->Init.DataType == CRYP_DATATYPE_8B)
+ {
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr));
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr));
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr));
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr));
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_16B)
+ {
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U);
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U);
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U);
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U);
+ }
+ else if (hcryp->Init.DataType == CRYP_DATATYPE_1B)
+ {
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr));
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr));
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr));
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr));
+ }
+ else
+ {
+ hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
+ ctr0addr += 4U;
+ hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
+ }
+ }
+#endif /*End of not defined CRYP_VER_2_2*/
+ /* Wait for OFNE flag to be raised */
+ tickstart = HAL_GetTick();
+ while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE))
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable the CRYP peripheral Clock */
+ __HAL_CRYP_DISABLE(hcryp);
+
+ /* Change state */
+ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Read the Auth TAG in the IN FIFO */
+ *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
+ tagaddr += 4U;
+ *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
+ tagaddr += 4U;
+ *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
+ tagaddr += 4U;
+ *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
+
+ /* Change the CRYP peripheral state */
+ hcryp->State = HAL_CRYP_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcryp);
+
+ /* Disable CRYP */
+ __HAL_CRYP_DISABLE(hcryp);
+ }
+ else
+ {
+ /* Busy error code field */
+ hcryp->ErrorCode = HAL_CRYP_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+#endif /* CRYP */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dac.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dac.c
new file mode 100644
index 0000000000..cf479e2cb9
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dac.c
@@ -0,0 +1,1534 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dac.c
+ * @author MCD Application Team
+ * @brief DAC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Digital to Analog Converter (DAC) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Errors functions
+ *
+ *
+ @verbatim
+ ==============================================================================
+ ##### DAC Peripheral features #####
+ ==============================================================================
+ [..]
+ *** DAC Channels ***
+ ====================
+ [..]
+ STM32H7 devices integrate two 12-bit Digital Analog Converters
+
+ The 2 converters (i.e. channel1 & channel2)
+ can be used independently or simultaneously (dual mode):
+ (#) DAC channel1 with DAC_OUT1 (PA4) as output or connected to on-chip
+ peripherals (ex. OPAMPs, comparators).
+ (#) DAC channel2 with DAC_OUT2 (PA5) as output or connected to on-chip
+ peripherals (ex. OPAMPs, comparators).
+
+ *** DAC Triggers ***
+ ====================
+ [..]
+ Digital to Analog conversion can be non-triggered using DAC_TRIGGER_NONE
+ and DAC_OUT1/DAC_OUT2 is available once writing to DHRx register.
+ [..]
+ Digital to Analog conversion can be triggered by:
+ (#) External event: EXTI Line 9 (any GPIOx_PIN_9) using DAC_TRIGGER_EXT_IT9.
+ The used pin (GPIOx_PIN_9) must be configured in input mode.
+
+ (#) Timers TRGO: TIM1, TIM2, TIM4, TIM5, TIM6, TIM7, TIM8, TIM15, TIM23 and TIM24
+ (DAC_TRIGGER_T1_TRGO, DAC_TRIGGER_T2_TRGO...)
+
+ (#) Low Power Timers TRGO: LPTIM1, LPTIM2 and LPTIM3
+ (DAC_TRIGGER_LPTIM1_OUT, DAC_TRIGGER_LPTIM2_OUT)
+
+ (#) High Resolution Timer TRGO: HRTIM1
+ (DAC_TRIGGER_HR1_TRGO1, DAC_TRIGGER_HR1_TRGO2)
+
+ (#) Software using DAC_TRIGGER_SOFTWARE
+ *** DAC Buffer mode feature ***
+ ===============================
+ [..]
+ Each DAC channel integrates an output buffer that can be used to
+ reduce the output impedance, and to drive external loads directly
+ without having to add an external operational amplifier.
+ To enable, the output buffer use
+ sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
+ [..]
+ (@) Refer to the device datasheet for more details about output
+ impedance value with and without output buffer.
+
+ *** DAC connect feature ***
+ ===============================
+ [..]
+ Each DAC channel can be connected internally.
+ To connect, use
+ sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_INTERNAL;
+ or
+ sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_BOTH;
+
+ *** GPIO configurations guidelines ***
+ =====================
+ [..]
+ When a DAC channel is used (ex channel1 on PA4) and the other is not
+ (ex channel2 on PA5 is configured in Analog and disabled).
+ Channel1 may disturb channel2 as coupling effect.
+ Note that there is no coupling on channel2 as soon as channel2 is turned on.
+ Coupling on adjacent channel could be avoided as follows:
+ when unused PA5 is configured as INPUT PULL-UP or DOWN.
+ PA5 is configured in ANALOG just before it is turned on.
+
+ *** DAC Sample and Hold feature ***
+ ========================
+ [..]
+ For each converter, 2 modes are supported: normal mode and
+ "sample and hold" mode (i.e. low power mode).
+ In the sample and hold mode, the DAC core converts data, then holds the
+ converted voltage on a capacitor. When not converting, the DAC cores and
+ buffer are completely turned off between samples and the DAC output is
+ tri-stated, therefore reducing the overall power consumption. A new
+ stabilization period is needed before each new conversion.
+
+ The sample and hold allow setting internal or external voltage @
+ low power consumption cost (output value can be at any given rate either
+ by CPU or DMA).
+
+ The Sample and hold block and registers uses either LSI & run in
+ several power modes: run mode, sleep mode, low power run, low power sleep
+ mode & stop1 mode.
+
+ Low power stop1 mode allows only static conversion.
+
+ To enable Sample and Hold mode
+ Enable LSI using HAL_RCC_OscConfig with RCC_OSCILLATORTYPE_LSI &
+ RCC_LSI_ON parameters.
+
+ Use DAC_InitStructure.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_ENABLE;
+ & DAC_ChannelConfTypeDef.DAC_SampleAndHoldConfig.DAC_SampleTime,
+ DAC_HoldTime & DAC_RefreshTime;
+
+ *** DAC calibration feature ***
+ ===================================
+ [..]
+ (#) The 2 converters (channel1 & channel2) provide calibration capabilities.
+ (++) Calibration aims at correcting some offset of output buffer.
+ (++) The DAC uses either factory calibration settings OR user defined
+ calibration (trimming) settings (i.e. trimming mode).
+ (++) The user defined settings can be figured out using self calibration
+ handled by HAL_DACEx_SelfCalibrate.
+ (++) HAL_DACEx_SelfCalibrate:
+ (+++) Runs automatically the calibration.
+ (+++) Enables the user trimming mode
+ (+++) Updates a structure with trimming values with fresh calibration
+ results.
+ The user may store the calibration results for larger
+ (ex monitoring the trimming as a function of temperature
+ for instance)
+
+ *** DAC wave generation feature ***
+ ===================================
+ [..]
+ Both DAC channels can be used to generate
+ (#) Noise wave
+ (#) Triangle wave
+
+ *** DAC data format ***
+ =======================
+ [..]
+ The DAC data format can be:
+ (#) 8-bit right alignment using DAC_ALIGN_8B_R
+ (#) 12-bit left alignment using DAC_ALIGN_12B_L
+ (#) 12-bit right alignment using DAC_ALIGN_12B_R
+
+ *** DAC data value to voltage correspondence ***
+ ================================================
+ [..]
+ The analog output voltage on each DAC channel pin is determined
+ by the following equation:
+ [..]
+ DAC_OUTx = VREF+ * DOR / 4095
+ (+) with DOR is the Data Output Register
+ [..]
+ VREF+ is the input voltage reference (refer to the device datasheet)
+ [..]
+ e.g. To set DAC_OUT1 to 0.7V, use
+ (+) Assuming that VREF+ = 3.3V, DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V
+
+ *** DMA requests ***
+ =====================
+ [..]
+ A DMA request can be generated when an external trigger (but not a software trigger)
+ occurs if DMA requests are enabled using HAL_DAC_Start_DMA().
+ DMA requests are mapped as following:
+ (#) DAC channel1: mapped on DMA_REQUEST_DAC1_CH1
+ (#) DAC channel2: mapped on DMA_REQUEST_DAC1_CH2
+
+ [..]
+ (@) For Dual mode and specific signal (Triangle and noise) generation please
+ refer to Extended Features Driver description
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (+) DAC APB clock must be enabled to get write access to DAC
+ registers using HAL_DAC_Init()
+ (+) Configure DAC_OUTx (DAC_OUT1: PA4, DAC_OUT2: PA5) in analog mode.
+ (+) Configure the DAC channel using HAL_DAC_ConfigChannel() function.
+ (+) Enable the DAC channel using HAL_DAC_Start() or HAL_DAC_Start_DMA() functions.
+
+ *** Calibration mode IO operation ***
+ ======================================
+ [..]
+ (+) Retrieve the factory trimming (calibration settings) using HAL_DACEx_GetTrimOffset()
+ (+) Run the calibration using HAL_DACEx_SelfCalibrate()
+ (+) Update the trimming while DAC running using HAL_DACEx_SetUserTrimming()
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Start the DAC peripheral using HAL_DAC_Start()
+ (+) To read the DAC last data output value, use the HAL_DAC_GetValue() function.
+ (+) Stop the DAC peripheral using HAL_DAC_Stop()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Start the DAC peripheral using HAL_DAC_Start_DMA(), at this stage the user specify the length
+ of data to be transferred at each end of conversion
+ First issued trigger will start the conversion of the value previously set by HAL_DAC_SetValue().
+ (+) At the middle of data transfer HAL_DAC_ConvHalfCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
+ function is executed and user can add his own code by customization of function pointer
+ HAL_DAC_ConvHalfCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
+ (+) At The end of data transfer HAL_DAC_ConvCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
+ function is executed and user can add his own code by customization of function pointer
+ HAL_DAC_ConvCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
+ (+) In case of transfer Error, HAL_DAC_ErrorCallbackCh1() function is executed and user can
+ add his own code by customization of function pointer HAL_DAC_ErrorCallbackCh1
+ (+) In case of DMA underrun, DAC interruption triggers and execute internal function HAL_DAC_IRQHandler.
+ HAL_DAC_DMAUnderrunCallbackCh1() or HAL_DACEx_DMAUnderrunCallbackCh2()
+ function is executed and user can add his own code by customization of function pointer
+ HAL_DAC_DMAUnderrunCallbackCh1() or HAL_DACEx_DMAUnderrunCallbackCh2() and
+ add his own code by customization of function pointer HAL_DAC_ErrorCallbackCh1()
+ (+) Stop the DAC peripheral using HAL_DAC_Stop_DMA()
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_DAC_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ Use Functions @ref HAL_DAC_RegisterCallback() to register a user callback,
+ it allows to register following callbacks:
+ (+) ConvCpltCallbackCh1 : callback when a half transfer is completed on Ch1.
+ (+) ConvHalfCpltCallbackCh1 : callback when a transfer is completed on Ch1.
+ (+) ErrorCallbackCh1 : callback when an error occurs on Ch1.
+ (+) DMAUnderrunCallbackCh1 : callback when an underrun error occurs on Ch1.
+ (+) ConvCpltCallbackCh2 : callback when a half transfer is completed on Ch2.
+ (+) ConvHalfCpltCallbackCh2 : callback when a transfer is completed on Ch2.
+ (+) ErrorCallbackCh2 : callback when an error occurs on Ch2.
+ (+) DMAUnderrunCallbackCh2 : callback when an underrun error occurs on Ch2.
+ (+) MspInitCallback : DAC MspInit.
+ (+) MspDeInitCallback : DAC MspdeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function @ref HAL_DAC_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function. It allows to reset following callbacks:
+ (+) ConvCpltCallbackCh1 : callback when a half transfer is completed on Ch1.
+ (+) ConvHalfCpltCallbackCh1 : callback when a transfer is completed on Ch1.
+ (+) ErrorCallbackCh1 : callback when an error occurs on Ch1.
+ (+) DMAUnderrunCallbackCh1 : callback when an underrun error occurs on Ch1.
+ (+) ConvCpltCallbackCh2 : callback when a half transfer is completed on Ch2.
+ (+) ConvHalfCpltCallbackCh2 : callback when a transfer is completed on Ch2.
+ (+) ErrorCallbackCh2 : callback when an error occurs on Ch2.
+ (+) DMAUnderrunCallbackCh2 : callback when an underrun error occurs on Ch2.
+ (+) MspInitCallback : DAC MspInit.
+ (+) MspDeInitCallback : DAC MspdeInit.
+ (+) All Callbacks
+ This function) takes as parameters the HAL peripheral handle and the Callback ID.
+
+ By default, after the @ref HAL_DAC_Init and if the state is HAL_DAC_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_DAC_Init
+ and @ref HAL_DAC_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_DAC_Init and @ref HAL_DAC_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 @ref HAL_DAC_RegisterCallback before calling @ref HAL_DAC_DeInit
+ or @ref HAL_DAC_Init function.
+
+ When The compilation define USE_HAL_DAC_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ *** DAC HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in DAC HAL driver.
+
+ (+) __HAL_DAC_ENABLE : Enable the DAC peripheral
+ (+) __HAL_DAC_DISABLE : Disable the DAC peripheral
+ (+) __HAL_DAC_CLEAR_FLAG: Clear the DAC's pending flags
+ (+) __HAL_DAC_GET_FLAG: Get the selected DAC's flag status
+
+ [..]
+ (@) You can refer to the DAC HAL driver header file for more useful macros
+
+@endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+#if defined(DAC1) || defined(DAC2)
+
+/** @defgroup DAC DAC
+ * @brief DAC driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup DAC_Private_Constants DAC Private Constants
+ * @{
+ */
+#define TIMEOUT_DAC_CALIBCONFIG 1U /* 1 ms */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions -------------------------------------------------------*/
+
+/** @defgroup DAC_Exported_Functions DAC Exported Functions
+ * @{
+ */
+
+/** @defgroup DAC_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the DAC.
+ (+) De-initialize the DAC.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the DAC peripheral according to the specified parameters
+ * in the DAC_InitStruct and initialize the associated handle.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Init(DAC_HandleTypeDef *hdac)
+{
+ /* Check DAC handle */
+ if (hdac == NULL)
+ {
+ return HAL_ERROR;
+ }
+ /* Check the parameters */
+ assert_param(IS_DAC_ALL_INSTANCE(hdac->Instance));
+
+ if (hdac->State == HAL_DAC_STATE_RESET)
+ {
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ /* Init the DAC Callback settings */
+ hdac->ConvCpltCallbackCh1 = HAL_DAC_ConvCpltCallbackCh1;
+ hdac->ConvHalfCpltCallbackCh1 = HAL_DAC_ConvHalfCpltCallbackCh1;
+ hdac->ErrorCallbackCh1 = HAL_DAC_ErrorCallbackCh1;
+ hdac->DMAUnderrunCallbackCh1 = HAL_DAC_DMAUnderrunCallbackCh1;
+
+ hdac->ConvCpltCallbackCh2 = HAL_DACEx_ConvCpltCallbackCh2;
+ hdac->ConvHalfCpltCallbackCh2 = HAL_DACEx_ConvHalfCpltCallbackCh2;
+ hdac->ErrorCallbackCh2 = HAL_DACEx_ErrorCallbackCh2;
+ hdac->DMAUnderrunCallbackCh2 = HAL_DACEx_DMAUnderrunCallbackCh2;
+
+ if (hdac->MspInitCallback == NULL)
+ {
+ hdac->MspInitCallback = HAL_DAC_MspInit;
+ }
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+
+ /* Allocate lock resource and initialize it */
+ hdac->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ /* Init the low level hardware */
+ hdac->MspInitCallback(hdac);
+#else
+ /* Init the low level hardware */
+ HAL_DAC_MspInit(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+ }
+
+ /* Initialize the DAC state*/
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Set DAC error code to none */
+ hdac->ErrorCode = HAL_DAC_ERROR_NONE;
+
+ /* Initialize the DAC state*/
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Deinitialize the DAC peripheral registers to their default reset values.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_DeInit(DAC_HandleTypeDef *hdac)
+{
+ /* Check DAC handle */
+ if (hdac == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_DAC_ALL_INSTANCE(hdac->Instance));
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ if (hdac->MspDeInitCallback == NULL)
+ {
+ hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ hdac->MspDeInitCallback(hdac);
+#else
+ /* DeInit the low level hardware */
+ HAL_DAC_MspDeInit(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+
+ /* Set DAC error code to none */
+ hdac->ErrorCode = HAL_DAC_ERROR_NONE;
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the DAC MSP.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the DAC MSP.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_MspDeInit(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_Exported_Functions_Group2 IO operation functions
+ * @brief IO operation functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start conversion.
+ (+) Stop conversion.
+ (+) Start conversion and enable DMA transfer.
+ (+) Stop conversion and disable DMA transfer.
+ (+) Get result of conversion.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables DAC and starts conversion of channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef *hdac, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Enable the Peripheral */
+ __HAL_DAC_ENABLE(hdac, Channel);
+
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* Check if software trigger enabled */
+ if ((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == DAC_TRIGGER_SOFTWARE)
+ {
+ /* Enable the selected DAC software conversion */
+ SET_BIT(hdac->Instance->SWTRIGR, DAC_SWTRIGR_SWTRIG1);
+ }
+ }
+ else
+ {
+ /* Check if software trigger enabled */
+ if ((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == (DAC_TRIGGER_SOFTWARE << (Channel & 0x10UL)))
+ {
+ /* Enable the selected DAC software conversion*/
+ SET_BIT(hdac->Instance->SWTRIGR, DAC_SWTRIGR_SWTRIG2);
+ }
+ }
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables DAC and stop conversion of channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef *hdac, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Disable the Peripheral */
+ __HAL_DAC_DISABLE(hdac, Channel);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables DAC and starts conversion of channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @param pData The destination peripheral Buffer address.
+ * @param Length The length of data to be transferred from memory to DAC peripheral
+ * @param Alignment Specifies the data alignment for DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
+ * @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
+ * @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length,
+ uint32_t Alignment)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_ALIGN(Alignment));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* Set the DMA transfer complete callback for channel1 */
+ hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
+
+ /* Set the DMA half transfer complete callback for channel1 */
+ hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
+
+ /* Set the DMA error callback for channel1 */
+ hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;
+
+ /* Enable the selected DAC channel1 DMA request */
+ SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
+
+ /* Case of use of channel 1 */
+ switch (Alignment)
+ {
+ case DAC_ALIGN_12B_R:
+ /* Get DHR12R1 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12R1;
+ break;
+ case DAC_ALIGN_12B_L:
+ /* Get DHR12L1 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12L1;
+ break;
+ case DAC_ALIGN_8B_R:
+ /* Get DHR8R1 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR8R1;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* Set the DMA transfer complete callback for channel2 */
+ hdac->DMA_Handle2->XferCpltCallback = DAC_DMAConvCpltCh2;
+
+ /* Set the DMA half transfer complete callback for channel2 */
+ hdac->DMA_Handle2->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh2;
+
+ /* Set the DMA error callback for channel2 */
+ hdac->DMA_Handle2->XferErrorCallback = DAC_DMAErrorCh2;
+
+ /* Enable the selected DAC channel2 DMA request */
+ SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
+
+ /* Case of use of channel 2 */
+ switch (Alignment)
+ {
+ case DAC_ALIGN_12B_R:
+ /* Get DHR12R2 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12R2;
+ break;
+ case DAC_ALIGN_12B_L:
+ /* Get DHR12L2 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12L2;
+ break;
+ case DAC_ALIGN_8B_R:
+ /* Get DHR8R2 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR8R2;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Enable the DMA Stream */
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* Enable the DAC DMA underrun interrupt */
+ __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
+
+ /* Enable the DMA Stream */
+ status = HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, Length);
+ }
+ else
+ {
+ /* Enable the DAC DMA underrun interrupt */
+ __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR2);
+
+ /* Enable the DMA Stream */
+ status = HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, Length);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdac);
+
+ if (status == HAL_OK)
+ {
+ /* Enable the Peripheral */
+ __HAL_DAC_ENABLE(hdac, Channel);
+ }
+ else
+ {
+ hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Disables DAC and stop conversion of channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Disable the selected DAC channel DMA request */
+ hdac->Instance->CR &= ~(DAC_CR_DMAEN1 << (Channel & 0x10UL));
+
+ /* Disable the Peripheral */
+ __HAL_DAC_DISABLE(hdac, Channel);
+
+ /* Disable the DMA Stream */
+
+ /* Channel1 is used */
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* Disable the DMA Stream */
+ status = HAL_DMA_Abort(hdac->DMA_Handle1);
+
+ /* Disable the DAC DMA underrun interrupt */
+ __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR1);
+ }
+ else /* Channel2 is used for */
+ {
+ /* Disable the DMA Stream */
+ status = HAL_DMA_Abort(hdac->DMA_Handle2);
+
+ /* Disable the DAC DMA underrun interrupt */
+ __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR2);
+ }
+
+ /* Check if DMA Stream effectively disabled */
+ if (status != HAL_OK)
+ {
+ /* Update DAC state machine to error */
+ hdac->State = HAL_DAC_STATE_ERROR;
+ }
+ else
+ {
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Handles DAC interrupt request
+ * This function uses the interruption of DMA
+ * underrun.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+void HAL_DAC_IRQHandler(DAC_HandleTypeDef *hdac)
+{
+ if (__HAL_DAC_GET_IT_SOURCE(hdac, DAC_IT_DMAUDR1))
+ {
+ /* Check underrun flag of DAC channel 1 */
+ if (__HAL_DAC_GET_FLAG(hdac, DAC_FLAG_DMAUDR1))
+ {
+ /* Change DAC state to error state */
+ hdac->State = HAL_DAC_STATE_ERROR;
+
+ /* Set DAC error code to chanel1 DMA underrun error */
+ SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_DMAUNDERRUNCH1);
+
+ /* Clear the underrun flag */
+ __HAL_DAC_CLEAR_FLAG(hdac, DAC_FLAG_DMAUDR1);
+
+ /* Disable the selected DAC channel1 DMA request */
+ CLEAR_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
+
+ /* Error callback */
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ hdac->DMAUnderrunCallbackCh1(hdac);
+#else
+ HAL_DAC_DMAUnderrunCallbackCh1(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+ }
+ }
+
+ if (__HAL_DAC_GET_IT_SOURCE(hdac, DAC_IT_DMAUDR2))
+ {
+ /* Check underrun flag of DAC channel 2 */
+ if (__HAL_DAC_GET_FLAG(hdac, DAC_FLAG_DMAUDR2))
+ {
+ /* Change DAC state to error state */
+ hdac->State = HAL_DAC_STATE_ERROR;
+
+ /* Set DAC error code to channel2 DMA underrun error */
+ SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_DMAUNDERRUNCH2);
+
+ /* Clear the underrun flag */
+ __HAL_DAC_CLEAR_FLAG(hdac, DAC_FLAG_DMAUDR2);
+
+ /* Disable the selected DAC channel2 DMA request */
+ CLEAR_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
+
+ /* Error callback */
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ hdac->DMAUnderrunCallbackCh2(hdac);
+#else
+ HAL_DACEx_DMAUnderrunCallbackCh2(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @brief Set the specified data holding register value for DAC channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @param Alignment Specifies the data alignment.
+ * This parameter can be one of the following values:
+ * @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
+ * @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
+ * @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
+ * @param Data Data to be loaded in the selected data holding register.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data)
+{
+ __IO uint32_t tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_ALIGN(Alignment));
+ assert_param(IS_DAC_DATA(Data));
+
+ tmp = (uint32_t)hdac->Instance;
+ if (Channel == DAC_CHANNEL_1)
+ {
+ tmp += DAC_DHR12R1_ALIGNMENT(Alignment);
+ }
+ else
+ {
+ tmp += DAC_DHR12R2_ALIGNMENT(Alignment);
+ }
+
+ /* Set the DAC channel selected data holding register */
+ *(__IO uint32_t *) tmp = Data;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Conversion complete callback in non-blocking mode for Channel1
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_ConvCpltCallbackCh1 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Conversion half DMA transfer callback in non-blocking mode for Channel1
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_ConvHalfCpltCallbackCh1 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Error DAC callback for Channel1.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_ErrorCallbackCh1(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_ErrorCallbackCh1 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DMA underrun DAC callback for channel1.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_DMAUnderrunCallbackCh1(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_DMAUnderrunCallbackCh1 could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure channels.
+ (+) Set the specified data holding register value for DAC channel.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the last data output value of the selected DAC channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval The selected DAC channel data output value.
+ */
+uint32_t HAL_DAC_GetValue(DAC_HandleTypeDef *hdac, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Returns the DAC channel data output register value */
+ if (Channel == DAC_CHANNEL_1)
+ {
+ return hdac->Instance->DOR1;
+ }
+ else
+ {
+ return hdac->Instance->DOR2;
+ }
+}
+
+/**
+ * @brief Configures the selected DAC channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param sConfig DAC configuration structure.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_ConfigChannel(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel)
+{
+ uint32_t tmpreg1;
+ uint32_t tmpreg2;
+ uint32_t tickstart;
+ uint32_t connectOnChip;
+
+ /* Check the DAC parameters */
+ assert_param(IS_DAC_TRIGGER(sConfig->DAC_Trigger));
+ assert_param(IS_DAC_OUTPUT_BUFFER_STATE(sConfig->DAC_OutputBuffer));
+ assert_param(IS_DAC_CHIP_CONNECTION(sConfig->DAC_ConnectOnChipPeripheral));
+ assert_param(IS_DAC_TRIMMING(sConfig->DAC_UserTrimming));
+ if ((sConfig->DAC_UserTrimming) == DAC_TRIMMING_USER)
+ {
+ assert_param(IS_DAC_TRIMMINGVALUE(sConfig->DAC_TrimmingValue));
+ }
+ assert_param(IS_DAC_SAMPLEANDHOLD(sConfig->DAC_SampleAndHold));
+ if ((sConfig->DAC_SampleAndHold) == DAC_SAMPLEANDHOLD_ENABLE)
+ {
+ assert_param(IS_DAC_SAMPLETIME(sConfig->DAC_SampleAndHoldConfig.DAC_SampleTime));
+ assert_param(IS_DAC_HOLDTIME(sConfig->DAC_SampleAndHoldConfig.DAC_HoldTime));
+ assert_param(IS_DAC_REFRESHTIME(sConfig->DAC_SampleAndHoldConfig.DAC_RefreshTime));
+ }
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Sample and hold configuration */
+ if (sConfig->DAC_SampleAndHold == DAC_SAMPLEANDHOLD_ENABLE)
+ {
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* SHSR1 can be written when BWST1 is cleared */
+ while (((hdac->Instance->SR) & DAC_SR_BWST1) != 0UL)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > TIMEOUT_DAC_CALIBCONFIG)
+ {
+ /* Update error code */
+ SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_TIMEOUT);
+
+ /* Change the DMA state */
+ hdac->State = HAL_DAC_STATE_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ HAL_Delay(1);
+ hdac->Instance->SHSR1 = sConfig->DAC_SampleAndHoldConfig.DAC_SampleTime;
+ }
+ else /* Channel 2 */
+ {
+ /* SHSR2 can be written when BWST2 is cleared */
+ while (((hdac->Instance->SR) & DAC_SR_BWST2) != 0UL)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > TIMEOUT_DAC_CALIBCONFIG)
+ {
+ /* Update error code */
+ SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_TIMEOUT);
+
+ /* Change the DMA state */
+ hdac->State = HAL_DAC_STATE_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ HAL_Delay(1U);
+ hdac->Instance->SHSR2 = sConfig->DAC_SampleAndHoldConfig.DAC_SampleTime;
+ }
+
+ /* HoldTime */
+ MODIFY_REG(hdac->Instance->SHHR, DAC_SHHR_THOLD1 << (Channel & 0x10UL), (sConfig->DAC_SampleAndHoldConfig.DAC_HoldTime) << (Channel & 0x10UL));
+ /* RefreshTime */
+ MODIFY_REG(hdac->Instance->SHRR, DAC_SHRR_TREFRESH1 << (Channel & 0x10UL), (sConfig->DAC_SampleAndHoldConfig.DAC_RefreshTime) << (Channel & 0x10UL));
+ }
+
+ if (sConfig->DAC_UserTrimming == DAC_TRIMMING_USER)
+ /* USER TRIMMING */
+ {
+ /* Get the DAC CCR value */
+ tmpreg1 = hdac->Instance->CCR;
+ /* Clear trimming value */
+ tmpreg1 &= ~(((uint32_t)(DAC_CCR_OTRIM1)) << (Channel & 0x10UL));
+ /* Configure for the selected trimming offset */
+ tmpreg2 = sConfig->DAC_TrimmingValue;
+ /* Calculate CCR register value depending on DAC_Channel */
+ tmpreg1 |= tmpreg2 << (Channel & 0x10UL);
+ /* Write to DAC CCR */
+ hdac->Instance->CCR = tmpreg1;
+ }
+ /* else factory trimming is used (factory setting are available at reset)*/
+ /* SW Nothing has nothing to do */
+
+ /* Get the DAC MCR value */
+ tmpreg1 = hdac->Instance->MCR;
+ /* Clear DAC_MCR_MODEx bits */
+ tmpreg1 &= ~(((uint32_t)(DAC_MCR_MODE1)) << (Channel & 0x10UL));
+ /* Configure for the selected DAC channel: mode, buffer output & on chip peripheral connect */
+ if (sConfig->DAC_ConnectOnChipPeripheral == DAC_CHIPCONNECT_EXTERNAL)
+ {
+ connectOnChip = 0x00000000UL;
+ }
+ else if (sConfig->DAC_ConnectOnChipPeripheral == DAC_CHIPCONNECT_INTERNAL)
+ {
+ connectOnChip = DAC_MCR_MODE1_0;
+ }
+ else /* (sConfig->DAC_ConnectOnChipPeripheral == DAC_CHIPCONNECT_BOTH) */
+ {
+ if (sConfig->DAC_OutputBuffer == DAC_OUTPUTBUFFER_ENABLE)
+ {
+ connectOnChip = DAC_MCR_MODE1_0;
+ }
+ else
+ {
+ connectOnChip = 0x00000000UL;
+ }
+ }
+ tmpreg2 = (sConfig->DAC_SampleAndHold | sConfig->DAC_OutputBuffer | connectOnChip);
+ /* Calculate MCR register value depending on DAC_Channel */
+ tmpreg1 |= tmpreg2 << (Channel & 0x10UL);
+ /* Write to DAC MCR */
+ hdac->Instance->MCR = tmpreg1;
+
+ /* DAC in normal operating mode hence clear DAC_CR_CENx bit */
+ CLEAR_BIT(hdac->Instance->CR, DAC_CR_CEN1 << (Channel & 0x10UL));
+
+ /* Get the DAC CR value */
+ tmpreg1 = hdac->Instance->CR;
+ /* Clear TENx, TSELx, WAVEx and MAMPx bits */
+ tmpreg1 &= ~(((uint32_t)(DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1)) << (Channel & 0x10UL));
+ /* Configure for the selected DAC channel: trigger */
+ /* Set TSELx and TENx bits according to DAC_Trigger value */
+ tmpreg2 = sConfig->DAC_Trigger;
+ /* Calculate CR register value depending on DAC_Channel */
+ tmpreg1 |= tmpreg2 << (Channel & 0x10UL);
+ /* Write to DAC CR */
+ hdac->Instance->CR = tmpreg1;
+ /* Disable wave generation */
+ hdac->Instance->CR &= ~(DAC_CR_WAVE1 << (Channel & 0x10UL));
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_Exported_Functions_Group4 Peripheral State and Errors functions
+ * @brief Peripheral State and Errors functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Errors functions #####
+ ==============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Check the DAC state.
+ (+) Check the DAC Errors.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief return the DAC handle state
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval HAL state
+ */
+HAL_DAC_StateTypeDef HAL_DAC_GetState(DAC_HandleTypeDef *hdac)
+{
+ /* Return DAC handle state */
+ return hdac->State;
+}
+
+
+/**
+ * @brief Return the DAC error code
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval DAC Error Code
+ */
+uint32_t HAL_DAC_GetError(DAC_HandleTypeDef *hdac)
+{
+ return hdac->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup DAC_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup DAC_Exported_Functions_Group1
+ * @{
+ */
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User DAC Callback
+ * To be used instead of the weak (surcharged) predefined callback
+ * @param hdac DAC handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DAC_ERROR_INVALID_CALLBACK DAC Error Callback ID
+ * @arg @ref HAL_DAC_CH1_COMPLETE_CB_ID DAC CH1 Complete Callback ID
+ * @arg @ref HAL_DAC_CH1_HALF_COMPLETE_CB_ID DAC CH1 Half Complete Callback ID
+ * @arg @ref HAL_DAC_CH1_ERROR_ID DAC CH1 Error Callback ID
+ * @arg @ref HAL_DAC_CH1_UNDERRUN_CB_ID DAC CH1 UnderRun Callback ID
+ * @arg @ref HAL_DAC_CH2_COMPLETE_CB_ID DAC CH2 Complete Callback ID
+ * @arg @ref HAL_DAC_CH2_HALF_COMPLETE_CB_ID DAC CH2 Half Complete Callback ID
+ * @arg @ref HAL_DAC_CH2_ERROR_ID DAC CH2 Error Callback ID
+ * @arg @ref HAL_DAC_CH2_UNDERRUN_CB_ID DAC CH2 UnderRun Callback ID
+ * @arg @ref HAL_DAC_MSPINIT_CB_ID DAC MSP Init Callback ID
+ * @arg @ref HAL_DAC_MSPDEINIT_CB_ID DAC MSP DeInit Callback ID
+ *
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_DAC_RegisterCallback(DAC_HandleTypeDef *hdac, HAL_DAC_CallbackIDTypeDef CallbackID,
+ pDAC_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ if (hdac->State == HAL_DAC_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DAC_CH1_COMPLETE_CB_ID :
+ hdac->ConvCpltCallbackCh1 = pCallback;
+ break;
+ case HAL_DAC_CH1_HALF_COMPLETE_CB_ID :
+ hdac->ConvHalfCpltCallbackCh1 = pCallback;
+ break;
+ case HAL_DAC_CH1_ERROR_ID :
+ hdac->ErrorCallbackCh1 = pCallback;
+ break;
+ case HAL_DAC_CH1_UNDERRUN_CB_ID :
+ hdac->DMAUnderrunCallbackCh1 = pCallback;
+ break;
+ case HAL_DAC_CH2_COMPLETE_CB_ID :
+ hdac->ConvCpltCallbackCh2 = pCallback;
+ break;
+ case HAL_DAC_CH2_HALF_COMPLETE_CB_ID :
+ hdac->ConvHalfCpltCallbackCh2 = pCallback;
+ break;
+ case HAL_DAC_CH2_ERROR_ID :
+ hdac->ErrorCallbackCh2 = pCallback;
+ break;
+ case HAL_DAC_CH2_UNDERRUN_CB_ID :
+ hdac->DMAUnderrunCallbackCh2 = pCallback;
+ break;
+ case HAL_DAC_MSPINIT_CB_ID :
+ hdac->MspInitCallback = pCallback;
+ break;
+ case HAL_DAC_MSPDEINIT_CB_ID :
+ hdac->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hdac->State == HAL_DAC_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DAC_MSPINIT_CB_ID :
+ hdac->MspInitCallback = pCallback;
+ break;
+ case HAL_DAC_MSPDEINIT_CB_ID :
+ hdac->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdac);
+ return status;
+}
+
+/**
+ * @brief Unregister a User DAC Callback
+ * DAC Callback is redirected to the weak (surcharged) predefined callback
+ * @param hdac DAC handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DAC_CH1_COMPLETE_CB_ID DAC CH1 tranfer Complete Callback ID
+ * @arg @ref HAL_DAC_CH1_HALF_COMPLETE_CB_ID DAC CH1 Half Complete Callback ID
+ * @arg @ref HAL_DAC_CH1_ERROR_ID DAC CH1 Error Callback ID
+ * @arg @ref HAL_DAC_CH1_UNDERRUN_CB_ID DAC CH1 UnderRun Callback ID
+ * @arg @ref HAL_DAC_CH2_COMPLETE_CB_ID DAC CH2 Complete Callback ID
+ * @arg @ref HAL_DAC_CH2_HALF_COMPLETE_CB_ID DAC CH2 Half Complete Callback ID
+ * @arg @ref HAL_DAC_CH2_ERROR_ID DAC CH2 Error Callback ID
+ * @arg @ref HAL_DAC_CH2_UNDERRUN_CB_ID DAC CH2 UnderRun Callback ID
+ * @arg @ref HAL_DAC_MSPINIT_CB_ID DAC MSP Init Callback ID
+ * @arg @ref HAL_DAC_MSPDEINIT_CB_ID DAC MSP DeInit Callback ID
+ * @arg @ref HAL_DAC_ALL_CB_ID DAC All callbacks
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_DAC_UnRegisterCallback(DAC_HandleTypeDef *hdac, HAL_DAC_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ if (hdac->State == HAL_DAC_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DAC_CH1_COMPLETE_CB_ID :
+ hdac->ConvCpltCallbackCh1 = HAL_DAC_ConvCpltCallbackCh1;
+ break;
+ case HAL_DAC_CH1_HALF_COMPLETE_CB_ID :
+ hdac->ConvHalfCpltCallbackCh1 = HAL_DAC_ConvHalfCpltCallbackCh1;
+ break;
+ case HAL_DAC_CH1_ERROR_ID :
+ hdac->ErrorCallbackCh1 = HAL_DAC_ErrorCallbackCh1;
+ break;
+ case HAL_DAC_CH1_UNDERRUN_CB_ID :
+ hdac->DMAUnderrunCallbackCh1 = HAL_DAC_DMAUnderrunCallbackCh1;
+ break;
+ case HAL_DAC_CH2_COMPLETE_CB_ID :
+ hdac->ConvCpltCallbackCh2 = HAL_DACEx_ConvCpltCallbackCh2;
+ break;
+ case HAL_DAC_CH2_HALF_COMPLETE_CB_ID :
+ hdac->ConvHalfCpltCallbackCh2 = HAL_DACEx_ConvHalfCpltCallbackCh2;
+ break;
+ case HAL_DAC_CH2_ERROR_ID :
+ hdac->ErrorCallbackCh2 = HAL_DACEx_ErrorCallbackCh2;
+ break;
+ case HAL_DAC_CH2_UNDERRUN_CB_ID :
+ hdac->DMAUnderrunCallbackCh2 = HAL_DACEx_DMAUnderrunCallbackCh2;
+ break;
+ case HAL_DAC_MSPINIT_CB_ID :
+ hdac->MspInitCallback = HAL_DAC_MspInit;
+ break;
+ case HAL_DAC_MSPDEINIT_CB_ID :
+ hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
+ break;
+ case HAL_DAC_ALL_CB_ID :
+ hdac->ConvCpltCallbackCh1 = HAL_DAC_ConvCpltCallbackCh1;
+ hdac->ConvHalfCpltCallbackCh1 = HAL_DAC_ConvHalfCpltCallbackCh1;
+ hdac->ErrorCallbackCh1 = HAL_DAC_ErrorCallbackCh1;
+ hdac->DMAUnderrunCallbackCh1 = HAL_DAC_DMAUnderrunCallbackCh1;
+ hdac->ConvCpltCallbackCh2 = HAL_DACEx_ConvCpltCallbackCh2;
+ hdac->ConvHalfCpltCallbackCh2 = HAL_DACEx_ConvHalfCpltCallbackCh2;
+ hdac->ErrorCallbackCh2 = HAL_DACEx_ErrorCallbackCh2;
+ hdac->DMAUnderrunCallbackCh2 = HAL_DACEx_DMAUnderrunCallbackCh2;
+ hdac->MspInitCallback = HAL_DAC_MspInit;
+ hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hdac->State == HAL_DAC_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DAC_MSPINIT_CB_ID :
+ hdac->MspInitCallback = HAL_DAC_MspInit;
+ break;
+ case HAL_DAC_MSPDEINIT_CB_ID :
+ hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdac);
+ return status;
+}
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup DAC_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief DMA conversion complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void DAC_DMAConvCpltCh1(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ hdac->ConvCpltCallbackCh1(hdac);
+#else
+ HAL_DAC_ConvCpltCallbackCh1(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+
+ hdac->State = HAL_DAC_STATE_READY;
+}
+
+/**
+ * @brief DMA half transfer complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void DAC_DMAHalfConvCpltCh1(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+ /* Conversion complete callback */
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ hdac->ConvHalfCpltCallbackCh1(hdac);
+#else
+ HAL_DAC_ConvHalfCpltCallbackCh1(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA error callback
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void DAC_DMAErrorCh1(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Set DAC error code to DMA error */
+ hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
+
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ hdac->ErrorCallbackCh1(hdac);
+#else
+ HAL_DAC_ErrorCallbackCh1(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+
+ hdac->State = HAL_DAC_STATE_READY;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* DAC1 || DAC2 */
+
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dac_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dac_ex.c
new file mode 100644
index 0000000000..75ceee92bf
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dac_ex.c
@@ -0,0 +1,869 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dac_ex.c
+ * @author MCD Application Team
+ * @brief Extended DAC HAL module driver.
+ * This file provides firmware functions to manage the extended
+ * functionalities of the DAC peripheral.
+ *
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ *** Dual mode IO operation ***
+ ==============================
+ (+) Use HAL_DACEx_DualStart() to enable both channel and start conversion
+ for dual mode operation.
+ If software trigger is selected, using HAL_DACEx_DualStart() will start
+ the conversion of the value previously set by HAL_DACEx_DualSetValue().
+ (+) Use HAL_DACEx_DualStop() to disable both channel and stop conversion
+ for dual mode operation.
+ (+) Use HAL_DACEx_DualStart_DMA() to enable both channel and start conversion
+ for dual mode operation using DMA to feed DAC converters.
+ First issued trigger will start the conversion of the value previously
+ set by HAL_DACEx_DualSetValue().
+ The same callbacks that are used in single mode are called in dual mode to notify
+ transfer completion (half complete or complete), errors or underrun.
+ (+) Use HAL_DACEx_DualStop_DMA() to disable both channel and stop conversion
+ for dual mode operation using DMA to feed DAC converters.
+ (+) When Dual mode is enabled (i.e. DAC Channel1 and Channel2 are used simultaneously) :
+ Use HAL_DACEx_DualGetValue() to get digital data to be converted and use
+ HAL_DACEx_DualSetValue() to set digital value to converted simultaneously in
+ Channel 1 and Channel 2.
+
+ *** Signal generation operation ***
+ ===================================
+ (+) Use HAL_DACEx_TriangleWaveGenerate() to generate Triangle signal.
+ (+) Use HAL_DACEx_NoiseWaveGenerate() to generate Noise signal.
+
+ (+) HAL_DACEx_SelfCalibrate to calibrate one DAC channel.
+ (+) HAL_DACEx_SetUserTrimming to set user trimming value.
+ (+) HAL_DACEx_GetTrimOffset to retrieve trimming value (factory setting
+ after reset, user setting if HAL_DACEx_SetUserTrimming have been used
+ at least one time after reset).
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+
+#if defined(DAC1) || defined(DAC2)
+
+/** @defgroup DACEx DACEx
+ * @brief DAC Extended HAL module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup DACEx_Exported_Functions DACEx Exported Functions
+ * @{
+ */
+
+/** @defgroup DACEx_Exported_Functions_Group2 IO operation functions
+ * @brief Extended IO operation functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Extended features functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start conversion.
+ (+) Stop conversion.
+ (+) Start conversion and enable DMA transfer.
+ (+) Stop conversion and disable DMA transfer.
+ (+) Get result of conversion.
+ (+) Get result of dual mode conversion.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables DAC and starts conversion of both channels.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_DualStart(DAC_HandleTypeDef *hdac)
+{
+ uint32_t tmp_swtrig = 0UL;
+
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Enable the Peripheral */
+ __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
+ __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
+
+ /* Check if software trigger enabled */
+ if ((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == DAC_CR_TEN1)
+ {
+ tmp_swtrig |= DAC_SWTRIGR_SWTRIG1;
+ }
+ if ((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == DAC_CR_TEN2)
+ {
+ tmp_swtrig |= DAC_SWTRIGR_SWTRIG2;
+ }
+ /* Enable the selected DAC software conversion*/
+ SET_BIT(hdac->Instance->SWTRIGR, tmp_swtrig);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables DAC and stop conversion of both channels.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_DualStop(DAC_HandleTypeDef *hdac)
+{
+
+ /* Disable the Peripheral */
+ __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
+ __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables DAC and starts conversion of both channel 1 and 2 of the same DAC.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The DAC channel that will request data from DMA.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @param pData The destination peripheral Buffer address.
+ * @param Length The length of data to be transferred from memory to DAC peripheral
+ * @param Alignment Specifies the data alignment for DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
+ * @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
+ * @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_DualStart_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length,
+ uint32_t Alignment)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tmpreg = 0UL;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_ALIGN(Alignment));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* Set the DMA transfer complete callback for channel1 */
+ hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
+
+ /* Set the DMA half transfer complete callback for channel1 */
+ hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
+
+ /* Set the DMA error callback for channel1 */
+ hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;
+
+ /* Enable the selected DAC channel1 DMA request */
+ SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
+ }
+ else
+ {
+ /* Set the DMA transfer complete callback for channel2 */
+ hdac->DMA_Handle2->XferCpltCallback = DAC_DMAConvCpltCh2;
+
+ /* Set the DMA half transfer complete callback for channel2 */
+ hdac->DMA_Handle2->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh2;
+
+ /* Set the DMA error callback for channel2 */
+ hdac->DMA_Handle2->XferErrorCallback = DAC_DMAErrorCh2;
+
+ /* Enable the selected DAC channel2 DMA request */
+ SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
+ }
+
+ switch (Alignment)
+ {
+ case DAC_ALIGN_12B_R:
+ /* Get DHR12R1 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12RD;
+ break;
+ case DAC_ALIGN_12B_L:
+ /* Get DHR12L1 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12LD;
+ break;
+ case DAC_ALIGN_8B_R:
+ /* Get DHR8R1 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR8RD;
+ break;
+ default:
+ break;
+ }
+
+ /* Enable the DMA channel */
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* Enable the DAC DMA underrun interrupt */
+ __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
+
+ /* Enable the DMA channel */
+ status = HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, Length);
+ }
+ else
+ {
+ /* Enable the DAC DMA underrun interrupt */
+ __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR2);
+
+ /* Enable the DMA channel */
+ status = HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, Length);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdac);
+
+ if (status == HAL_OK)
+ {
+ /* Enable the Peripheral */
+ __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
+ __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
+ }
+ else
+ {
+ hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Disables DAC and stop conversion both channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The DAC channel that requests data from DMA.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_DualStop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel)
+{
+ HAL_StatusTypeDef status;
+
+
+ /* Disable the selected DAC channel DMA request */
+ CLEAR_BIT(hdac->Instance->CR, DAC_CR_DMAEN2 | DAC_CR_DMAEN1);
+
+ /* Disable the Peripheral */
+ __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
+ __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
+
+ /* Disable the DMA channel */
+
+ /* Channel1 is used */
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* Disable the DMA channel */
+ status = HAL_DMA_Abort(hdac->DMA_Handle1);
+
+ /* Disable the DAC DMA underrun interrupt */
+ __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR1);
+ }
+ else
+ {
+ /* Disable the DMA channel */
+ status = HAL_DMA_Abort(hdac->DMA_Handle2);
+
+ /* Disable the DAC DMA underrun interrupt */
+ __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR2);
+ }
+
+ /* Check if DMA Channel effectively disabled */
+ if (status != HAL_OK)
+ {
+ /* Update DAC state machine to error */
+ hdac->State = HAL_DAC_STATE_ERROR;
+ }
+ else
+ {
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Enable or disable the selected DAC channel wave generation.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @param Amplitude Select max triangle amplitude.
+ * This parameter can be one of the following values:
+ * @arg DAC_TRIANGLEAMPLITUDE_1: Select max triangle amplitude of 1
+ * @arg DAC_TRIANGLEAMPLITUDE_3: Select max triangle amplitude of 3
+ * @arg DAC_TRIANGLEAMPLITUDE_7: Select max triangle amplitude of 7
+ * @arg DAC_TRIANGLEAMPLITUDE_15: Select max triangle amplitude of 15
+ * @arg DAC_TRIANGLEAMPLITUDE_31: Select max triangle amplitude of 31
+ * @arg DAC_TRIANGLEAMPLITUDE_63: Select max triangle amplitude of 63
+ * @arg DAC_TRIANGLEAMPLITUDE_127: Select max triangle amplitude of 127
+ * @arg DAC_TRIANGLEAMPLITUDE_255: Select max triangle amplitude of 255
+ * @arg DAC_TRIANGLEAMPLITUDE_511: Select max triangle amplitude of 511
+ * @arg DAC_TRIANGLEAMPLITUDE_1023: Select max triangle amplitude of 1023
+ * @arg DAC_TRIANGLEAMPLITUDE_2047: Select max triangle amplitude of 2047
+ * @arg DAC_TRIANGLEAMPLITUDE_4095: Select max triangle amplitude of 4095
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Enable the triangle wave generation for the selected DAC channel */
+ MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL), (DAC_CR_WAVE1_1 | Amplitude) << (Channel & 0x10UL));
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable or disable the selected DAC channel wave generation.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @param Amplitude Unmask DAC channel LFSR for noise wave generation.
+ * This parameter can be one of the following values:
+ * @arg DAC_LFSRUNMASK_BIT0: Unmask DAC channel LFSR bit0 for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS1_0: Unmask DAC channel LFSR bit[1:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS2_0: Unmask DAC channel LFSR bit[2:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS3_0: Unmask DAC channel LFSR bit[3:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS4_0: Unmask DAC channel LFSR bit[4:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS5_0: Unmask DAC channel LFSR bit[5:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS6_0: Unmask DAC channel LFSR bit[6:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS7_0: Unmask DAC channel LFSR bit[7:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS8_0: Unmask DAC channel LFSR bit[8:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS9_0: Unmask DAC channel LFSR bit[9:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS10_0: Unmask DAC channel LFSR bit[10:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS11_0: Unmask DAC channel LFSR bit[11:0] for noise wave generation
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Enable the noise wave generation for the selected DAC channel */
+ MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL), (DAC_CR_WAVE1_0 | Amplitude) << (Channel & 0x10UL));
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the specified data holding register value for dual DAC channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Alignment Specifies the data alignment for dual channel DAC.
+ * This parameter can be one of the following values:
+ * DAC_ALIGN_8B_R: 8bit right data alignment selected
+ * DAC_ALIGN_12B_L: 12bit left data alignment selected
+ * DAC_ALIGN_12B_R: 12bit right data alignment selected
+ * @param Data1 Data for DAC Channel1 to be loaded in the selected data holding register.
+ * @param Data2 Data for DAC Channel2 to be loaded in the selected data holding register.
+ * @note In dual mode, a unique register access is required to write in both
+ * DAC channels at the same time.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_DualSetValue(DAC_HandleTypeDef *hdac, uint32_t Alignment, uint32_t Data1, uint32_t Data2)
+{
+ uint32_t data;
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_ALIGN(Alignment));
+ assert_param(IS_DAC_DATA(Data1));
+ assert_param(IS_DAC_DATA(Data2));
+
+ /* Calculate and set dual DAC data holding register value */
+ if (Alignment == DAC_ALIGN_8B_R)
+ {
+ data = ((uint32_t)Data2 << 8U) | Data1;
+ }
+ else
+ {
+ data = ((uint32_t)Data2 << 16U) | Data1;
+ }
+
+ tmp = (uint32_t)hdac->Instance;
+ tmp += DAC_DHR12RD_ALIGNMENT(Alignment);
+
+ /* Set the dual DAC selected data holding register */
+ *(__IO uint32_t *)tmp = data;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Conversion complete callback in non-blocking mode for Channel2.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DACEx_ConvCpltCallbackCh2 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Conversion half DMA transfer callback in non-blocking mode for Channel2.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DACEx_ConvHalfCpltCallbackCh2 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Error DAC callback for Channel2.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DACEx_ErrorCallbackCh2 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DMA underrun DAC callback for Channel2.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DACEx_DMAUnderrunCallbackCh2 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Run the self calibration of one DAC channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param sConfig DAC channel configuration structure.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval Updates DAC_TrimmingValue. , DAC_UserTrimming set to DAC_UserTrimming
+ * @retval HAL status
+ * @note Calibration runs about 7 ms.
+ */
+HAL_StatusTypeDef HAL_DACEx_SelfCalibrate(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ __IO uint32_t tmp;
+ uint32_t trimmingvalue;
+ uint32_t delta;
+
+ /* store/restore channel configuration structure purpose */
+ uint32_t oldmodeconfiguration;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Check the DAC handle allocation */
+ /* Check if DAC running */
+ if (hdac == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if (hdac->State == HAL_DAC_STATE_BUSY)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Store configuration */
+ oldmodeconfiguration = (hdac->Instance->MCR & (DAC_MCR_MODE1 << (Channel & 0x10UL)));
+
+ /* Disable the selected DAC channel */
+ CLEAR_BIT((hdac->Instance->CR), (DAC_CR_EN1 << (Channel & 0x10UL)));
+
+ /* Set mode in MCR for calibration */
+ MODIFY_REG(hdac->Instance->MCR, (DAC_MCR_MODE1 << (Channel & 0x10UL)), 0U);
+
+ /* Set DAC Channel1 DHR register to the middle value */
+ tmp = (uint32_t)hdac->Instance;
+
+ if (Channel == DAC_CHANNEL_1)
+ {
+ tmp += DAC_DHR12R1_ALIGNMENT(DAC_ALIGN_12B_R);
+ }
+ else
+ {
+ tmp += DAC_DHR12R2_ALIGNMENT(DAC_ALIGN_12B_R);
+ }
+
+ *(__IO uint32_t *) tmp = 0x0800UL;
+
+ /* Enable the selected DAC channel calibration */
+ /* i.e. set DAC_CR_CENx bit */
+ SET_BIT((hdac->Instance->CR), (DAC_CR_CEN1 << (Channel & 0x10UL)));
+
+ /* Init trimming counter */
+ /* Medium value */
+ trimmingvalue = 16UL;
+ delta = 8UL;
+ while (delta != 0UL)
+ {
+ /* Set candidate trimming */
+ MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (trimmingvalue << (Channel & 0x10UL)));
+
+ /* tOFFTRIMmax delay x ms as per datasheet (electrical characteristics */
+ /* i.e. minimum time needed between two calibration steps */
+ HAL_Delay(1);
+
+ if ((hdac->Instance->SR & (DAC_SR_CAL_FLAG1 << (Channel & 0x10UL))) == (DAC_SR_CAL_FLAG1 << (Channel & 0x10UL)))
+ {
+ /* DAC_SR_CAL_FLAGx is HIGH try higher trimming */
+ trimmingvalue -= delta;
+ }
+ else
+ {
+ /* DAC_SR_CAL_FLAGx is LOW try lower trimming */
+ trimmingvalue += delta;
+ }
+ delta >>= 1UL;
+ }
+
+ /* Still need to check if right calibration is current value or one step below */
+ /* Indeed the first value that causes the DAC_SR_CAL_FLAGx bit to change from 0 to 1 */
+ /* Set candidate trimming */
+ MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (trimmingvalue << (Channel & 0x10UL)));
+
+ /* tOFFTRIMmax delay x ms as per datasheet (electrical characteristics */
+ /* i.e. minimum time needed between two calibration steps */
+ HAL_Delay(1U);
+
+ if ((hdac->Instance->SR & (DAC_SR_CAL_FLAG1 << (Channel & 0x10UL))) == 0UL)
+ {
+ /* Trimming is actually one value more */
+ trimmingvalue++;
+ /* Set right trimming */
+ MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (trimmingvalue << (Channel & 0x10UL)));
+ }
+
+ /* Disable the selected DAC channel calibration */
+ /* i.e. clear DAC_CR_CENx bit */
+ CLEAR_BIT((hdac->Instance->CR), (DAC_CR_CEN1 << (Channel & 0x10UL)));
+
+ sConfig->DAC_TrimmingValue = trimmingvalue;
+ sConfig->DAC_UserTrimming = DAC_TRIMMING_USER;
+
+ /* Restore configuration */
+ MODIFY_REG(hdac->Instance->MCR, (DAC_MCR_MODE1 << (Channel & 0x10UL)), oldmodeconfiguration);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set the trimming mode and trimming value (user trimming mode applied).
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param sConfig DAC configuration structure updated with new DAC trimming value.
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @param NewTrimmingValue DAC new trimming value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_SetUserTrimming(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel,
+ uint32_t NewTrimmingValue)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_NEWTRIMMINGVALUE(NewTrimmingValue));
+
+ /* Check the DAC handle allocation */
+ if (hdac == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Set new trimming */
+ MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (NewTrimmingValue << (Channel & 0x10UL)));
+
+ /* Update trimming mode */
+ sConfig->DAC_UserTrimming = DAC_TRIMMING_USER;
+ sConfig->DAC_TrimmingValue = NewTrimmingValue;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+ }
+ return status;
+}
+
+/**
+ * @brief Return the DAC trimming value.
+ * @param hdac DAC handle
+ * @param Channel The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval Trimming value : range: 0->31
+ *
+ */
+uint32_t HAL_DACEx_GetTrimOffset(DAC_HandleTypeDef *hdac, uint32_t Channel)
+{
+ /* Check the parameter */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Retrieve trimming */
+ return ((hdac->Instance->CCR & (DAC_CCR_OTRIM1 << (Channel & 0x10UL))) >> (Channel & 0x10UL));
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DACEx_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Set the specified data holding register value for DAC channel.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the last data output value of the selected DAC channel.
+ * @param hdac pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval The selected DAC channel data output value.
+ */
+uint32_t HAL_DACEx_DualGetValue(DAC_HandleTypeDef *hdac)
+{
+ uint32_t tmp = 0UL;
+
+ tmp |= hdac->Instance->DOR1;
+
+ tmp |= hdac->Instance->DOR2 << 16UL;
+
+ /* Returns the DAC channel data output register value */
+ return tmp;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup DACEx_Private_Functions DACEx private functions
+ * @brief Extended private functions
+ * @{
+ */
+
+/**
+ * @brief DMA conversion complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void DAC_DMAConvCpltCh2(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ hdac->ConvCpltCallbackCh2(hdac);
+#else
+ HAL_DACEx_ConvCpltCallbackCh2(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+
+ hdac->State = HAL_DAC_STATE_READY;
+}
+
+/**
+ * @brief DMA half transfer complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+ /* Conversion complete callback */
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ hdac->ConvHalfCpltCallbackCh2(hdac);
+#else
+ HAL_DACEx_ConvHalfCpltCallbackCh2(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA error callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void DAC_DMAErrorCh2(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Set DAC error code to DMA error */
+ hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
+
+#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
+ hdac->ErrorCallbackCh2(hdac);
+#else
+ HAL_DACEx_ErrorCallbackCh2(hdac);
+#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
+
+ hdac->State = HAL_DAC_STATE_READY;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* DAC1 || DAC2 */
+
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dcmi.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dcmi.c
new file mode 100644
index 0000000000..ac25ecc549
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dcmi.c
@@ -0,0 +1,1227 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dcmi.c
+ * @author MCD Application Team
+ * @brief DCMI HAL module driver
+ * This file provides firmware functions to manage the following
+ * functionalities of the Digital Camera Interface (DCMI) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Error functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The sequence below describes how to use this driver to capture image
+ from a camera module connected to the DCMI Interface.
+ This sequence does not take into account the configuration of the
+ camera module, which should be made before to configure and enable
+ the DCMI to capture images.
+
+ (#) Program the required configuration through following parameters:
+ horizontal and vertical polarity, pixel clock polarity, Capture Rate,
+ Synchronization Mode, code of the frame delimiter and data width
+ using HAL_DCMI_Init() function.
+
+ (#) Configure the selected DMA stream to transfer Data from DCMI DR
+ register to the destination memory buffer.
+
+ (#) Program the required configuration through following parameters:
+ DCMI mode, destination memory Buffer address and the data length
+ and enable capture using HAL_DCMI_Start_DMA() function.
+
+ (#) Optionally, configure and Enable the CROP feature to select a rectangular
+ window from the received image using HAL_DCMI_ConfigCrop()
+ and HAL_DCMI_EnableCrop() functions
+
+ (#) The capture can be stopped using HAL_DCMI_Stop() function.
+
+ (#) To control DCMI state you can use the function HAL_DCMI_GetState().
+
+ *** Callback registration ***
+ =============================================
+
+ The compilation flag USE_HAL_DCMI_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions HAL_DCMI_RegisterCallback() to register an interrupt callback.
+
+ Function HAL_DCMI_RegisterCallback() allows to register following callbacks:
+ (+) LineEventCallback : callback for DCMI line event.
+ (+) FrameEventCallback : callback for DCMI Frame event.
+ (+) VsyncEventCallback : callback for DCMI Vsync event.
+ (+) ErrorCallback : callback for error detection.
+ (+) 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.
+
+ Use function HAL_DCMI_UnRegisterCallback to reset a callback to the default weak function.
+ HAL_DCMI_UnRegisterCallback takes as parameters the HAL peripheral handle and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) LineEventCallback : callback for DCMI line event.
+ (+) FrameEventCallback : callback for DCMI Frame event.
+ (+) VsyncEventCallback : callback for DCMI Vsync event.
+ (+) ErrorCallback : callback for error detection.
+ (+) MspInitCallback : callback for Msp Init.
+ (+) MspDeInitCallback : callback for Msp DeInit.
+
+ By default, after the HAL_DCMI_Init() and when the state is HAL_DCMI_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples HAL_DCMI_LineEventCallback(), HAL_DCMI_FrameEventCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the HAL_DCMI_Init()/ HAL_DCMI_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ If MspInit or MspDeInit are not null, the HAL_DCMI_Init()/ HAL_DCMI_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+
+ Callbacks can be registered/unregistered in HAL_DCMI_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in HAL_DCMI_STATE_READY or HAL_DCMI_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_DCMI_RegisterCallback() before calling HAL_DCMI_DeInit() or HAL_DCMI_Init() function.
+
+ When the compilation flag USE_HAL_DCMI_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.
+
+ *** DCMI HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in DCMI HAL driver.
+
+ (+) __HAL_DCMI_ENABLE: Enable the DCMI peripheral.
+ (+) __HAL_DCMI_DISABLE: Disable the DCMI peripheral.
+ (+) __HAL_DCMI_GET_FLAG: Get the DCMI pending flags.
+ (+) __HAL_DCMI_CLEAR_FLAG: Clear the DCMI pending flags.
+ (+) __HAL_DCMI_ENABLE_IT: Enable the specified DCMI interrupts.
+ (+) __HAL_DCMI_DISABLE_IT: Disable the specified DCMI interrupts.
+ (+) __HAL_DCMI_GET_IT_SOURCE: Check whether the specified DCMI interrupt has occurred or not.
+
+ [..]
+ (@) You can refer to the DCMI HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+/** @defgroup DCMI DCMI
+ * @brief DCMI HAL module driver
+ * @{
+ */
+
+#ifdef HAL_DCMI_MODULE_ENABLED
+#if defined (DCMI)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define HAL_TIMEOUT_DCMI_STOP ((uint32_t)1000) /* Set timeout to 1s */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma);
+static void DCMI_DMAError(DMA_HandleTypeDef *hdma);
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup DCMI_Exported_Functions DCMI Exported Functions
+ * @{
+ */
+
+/** @defgroup DCMI_Exported_Functions_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the DCMI
+ (+) De-initialize the DCMI
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the DCMI according to the specified
+ * parameters in the DCMI_InitTypeDef and create the associated handle.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_Init(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Check the DCMI peripheral state */
+ if (hdcmi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check function parameters */
+ assert_param(IS_DCMI_ALL_INSTANCE(hdcmi->Instance));
+ assert_param(IS_DCMI_PCKPOLARITY(hdcmi->Init.PCKPolarity));
+ assert_param(IS_DCMI_VSPOLARITY(hdcmi->Init.VSPolarity));
+ assert_param(IS_DCMI_HSPOLARITY(hdcmi->Init.HSPolarity));
+ assert_param(IS_DCMI_SYNCHRO(hdcmi->Init.SynchroMode));
+ assert_param(IS_DCMI_CAPTURE_RATE(hdcmi->Init.CaptureRate));
+ assert_param(IS_DCMI_EXTENDED_DATA(hdcmi->Init.ExtendedDataMode));
+ assert_param(IS_DCMI_MODE_JPEG(hdcmi->Init.JPEGMode));
+
+ assert_param(IS_DCMI_BYTE_SELECT_MODE(hdcmi->Init.ByteSelectMode));
+ assert_param(IS_DCMI_BYTE_SELECT_START(hdcmi->Init.ByteSelectStart));
+ assert_param(IS_DCMI_LINE_SELECT_MODE(hdcmi->Init.LineSelectMode));
+ assert_param(IS_DCMI_LINE_SELECT_START(hdcmi->Init.LineSelectStart));
+
+ if (hdcmi->State == HAL_DCMI_STATE_RESET)
+ {
+ /* Init the DCMI Callback settings */
+#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
+ /* Reset callback pointers to the weak predefined callbacks */
+ hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback */
+ hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback */
+ hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback; /* Legacy weak LineEventCallback */
+ hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback; /* Legacy weak ErrorCallback */
+
+ if (hdcmi->MspInitCallback == NULL)
+ {
+ /* Legacy weak MspInit Callback */
+ hdcmi->MspInitCallback = HAL_DCMI_MspInit;
+ }
+ /* Initialize the low level hardware (MSP) */
+ hdcmi->MspInitCallback(hdcmi);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_DCMI_MspInit(hdcmi);
+#endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */
+ }
+
+ /* Change the DCMI state */
+ hdcmi->State = HAL_DCMI_STATE_BUSY;
+
+ if (hdcmi->Init.ExtendedDataMode != DCMI_EXTEND_DATA_8B)
+ {
+ /* Byte select mode must be programmed to the reset value if the extended mode
+ is not set to 8-bit data capture on every pixel clock */
+ hdcmi->Init.ByteSelectMode = DCMI_BSM_ALL;
+ }
+ /* Configures the HS, VS, DE and PC polarity */
+ hdcmi->Instance->CR &= ~(DCMI_CR_PCKPOL | DCMI_CR_HSPOL | DCMI_CR_VSPOL | DCMI_CR_EDM_0 | \
+ DCMI_CR_EDM_1 | DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 | DCMI_CR_JPEG | \
+ DCMI_CR_ESS | DCMI_CR_BSM_0 | DCMI_CR_BSM_1 | DCMI_CR_OEBS | \
+ DCMI_CR_LSM | DCMI_CR_OELS);
+
+ hdcmi->Instance->CR |= (uint32_t)(hdcmi->Init.SynchroMode | hdcmi->Init.CaptureRate | \
+ hdcmi->Init.VSPolarity | hdcmi->Init.HSPolarity | \
+ hdcmi->Init.PCKPolarity | hdcmi->Init.ExtendedDataMode | \
+ hdcmi->Init.JPEGMode | hdcmi->Init.ByteSelectMode | \
+ hdcmi->Init.ByteSelectStart | hdcmi->Init.LineSelectMode | \
+ hdcmi->Init.LineSelectStart);
+
+ if (hdcmi->Init.SynchroMode == DCMI_SYNCHRO_EMBEDDED)
+ {
+ hdcmi->Instance->ESCR = (((uint32_t)hdcmi->Init.SyncroCode.FrameStartCode) | \
+ ((uint32_t)hdcmi->Init.SyncroCode.LineStartCode << DCMI_ESCR_LSC_Pos) | \
+ ((uint32_t)hdcmi->Init.SyncroCode.LineEndCode << DCMI_ESCR_LEC_Pos) | \
+ ((uint32_t)hdcmi->Init.SyncroCode.FrameEndCode << DCMI_ESCR_FEC_Pos));
+
+ }
+
+ /* Enable the Line, Vsync, Error and Overrun interrupts */
+ __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR);
+
+ /* Update error code */
+ hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE;
+
+ /* Initialize the DCMI state*/
+ hdcmi->State = HAL_DCMI_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deinitializes the DCMI peripheral registers to their default reset
+ * values.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_DCMI_DeInit(DCMI_HandleTypeDef *hdcmi)
+{
+#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
+ if (hdcmi->MspDeInitCallback == NULL)
+ {
+ hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
+ }
+ /* De-Initialize the low level hardware (MSP) */
+ hdcmi->MspDeInitCallback(hdcmi);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+ HAL_DCMI_MspDeInit(hdcmi);
+#endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */
+
+ /* Update error code */
+ hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE;
+
+ /* Initialize the DCMI state*/
+ hdcmi->State = HAL_DCMI_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdcmi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the DCMI MSP.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval None
+ */
+__weak void HAL_DCMI_MspInit(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdcmi);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DCMI_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes the DCMI MSP.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval None
+ */
+__weak void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdcmi);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DCMI_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+/** @defgroup DCMI_Exported_Functions_Group2 IO operation functions
+ * @brief IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure destination address and data length and
+ Enables DCMI DMA request and enables DCMI capture
+ (+) Stop the DCMI capture.
+ (+) Handles DCMI interrupt request.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables DCMI DMA request and enables DCMI capture
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @param DCMI_Mode DCMI capture mode snapshot or continuous grab.
+ * @param pData The destination memory Buffer address (LCD Frame buffer).
+ * @param Length The length of capture to be transferred.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_Start_DMA(DCMI_HandleTypeDef *hdcmi, uint32_t DCMI_Mode, uint32_t pData, uint32_t Length)
+{
+ /* Initialize the second memory address */
+ uint32_t SecondMemAddress;
+
+ /* Check function parameters */
+ assert_param(IS_DCMI_CAPTURE_MODE(DCMI_Mode));
+
+ /* Process Locked */
+ __HAL_LOCK(hdcmi);
+
+ /* Lock the DCMI peripheral state */
+ hdcmi->State = HAL_DCMI_STATE_BUSY;
+
+ /* Enable DCMI by setting DCMIEN bit */
+ __HAL_DCMI_ENABLE(hdcmi);
+
+ /* Configure the DCMI Mode */
+ hdcmi->Instance->CR &= ~(DCMI_CR_CM);
+ hdcmi->Instance->CR |= (uint32_t)(DCMI_Mode);
+
+ /* Set the DMA memory0 conversion complete callback */
+ hdcmi->DMA_Handle->XferCpltCallback = DCMI_DMAXferCplt;
+
+ /* Set the DMA error callback */
+ hdcmi->DMA_Handle->XferErrorCallback = DCMI_DMAError;
+
+ /* Set the dma abort callback */
+ hdcmi->DMA_Handle->XferAbortCallback = NULL;
+
+ /* Reset transfer counters value */
+ hdcmi->XferCount = 0;
+ hdcmi->XferTransferNumber = 0;
+ hdcmi->XferSize = 0;
+ hdcmi->pBuffPtr = 0;
+
+ if (Length <= 0xFFFFU)
+ {
+ /* Enable the DMA Stream */
+ if (HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, Length) != HAL_OK)
+ {
+ /* Set Error Code */
+ hdcmi->ErrorCode = HAL_DCMI_ERROR_DMA;
+ /* Change DCMI state */
+ hdcmi->State = HAL_DCMI_STATE_READY;
+ /* Release Lock */
+ __HAL_UNLOCK(hdcmi);
+ /* Return function status */
+ return HAL_ERROR;
+ }
+ }
+ else /* DCMI_DOUBLE_BUFFER Mode */
+ {
+ /* Set the DMA memory1 conversion complete callback */
+ hdcmi->DMA_Handle->XferM1CpltCallback = DCMI_DMAXferCplt;
+
+ /* Initialize transfer parameters */
+ hdcmi->XferCount = 1;
+ hdcmi->XferSize = Length;
+ hdcmi->pBuffPtr = pData;
+
+ /* Get the number of buffer */
+ while (hdcmi->XferSize > 0xFFFFU)
+ {
+ hdcmi->XferSize = (hdcmi->XferSize / 2U);
+ hdcmi->XferCount = hdcmi->XferCount * 2U;
+ }
+
+ /* Update DCMI counter and transfer number*/
+ hdcmi->XferCount = (hdcmi->XferCount - 2U);
+ hdcmi->XferTransferNumber = hdcmi->XferCount;
+
+ /* Update second memory address */
+ SecondMemAddress = (uint32_t)(pData + (4U * hdcmi->XferSize));
+
+ /* Start DMA multi buffer transfer */
+ if (HAL_DMAEx_MultiBufferStart_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, SecondMemAddress, hdcmi->XferSize) != HAL_OK)
+ {
+ /* Set Error Code */
+ hdcmi->ErrorCode = HAL_DCMI_ERROR_DMA;
+ /* Change DCMI state */
+ hdcmi->State = HAL_DCMI_STATE_READY;
+ /* Release Lock */
+ __HAL_UNLOCK(hdcmi);
+ /* Return function status */
+ return HAL_ERROR;
+ }
+ }
+
+ /* Enable Capture */
+ hdcmi->Instance->CR |= DCMI_CR_CAPTURE;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdcmi);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable DCMI DMA request and Disable DCMI capture
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_Stop(DCMI_HandleTypeDef *hdcmi)
+{
+ register uint32_t count = HAL_TIMEOUT_DCMI_STOP * (SystemCoreClock / 8U / 1000U);
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hdcmi);
+
+ /* Lock the DCMI peripheral state */
+ hdcmi->State = HAL_DCMI_STATE_BUSY;
+
+ /* Disable Capture */
+ hdcmi->Instance->CR &= ~(DCMI_CR_CAPTURE);
+
+ /* Check if the DCMI capture effectively disabled */
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Update error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
+
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+ while ((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0U);
+
+ /* Disable the DCMI */
+ __HAL_DCMI_DISABLE(hdcmi);
+
+ /* Disable the DMA */
+ (void)HAL_DMA_Abort(hdcmi->DMA_Handle);
+
+ /* Update error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_NONE;
+
+ /* Change DCMI state */
+ hdcmi->State = HAL_DCMI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdcmi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Suspend DCMI capture
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_Suspend(DCMI_HandleTypeDef *hdcmi)
+{
+ register uint32_t count = HAL_TIMEOUT_DCMI_STOP * (SystemCoreClock / 8U / 1000U);
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hdcmi);
+
+ if (hdcmi->State == HAL_DCMI_STATE_BUSY)
+ {
+ /* Change DCMI state */
+ hdcmi->State = HAL_DCMI_STATE_SUSPENDED;
+
+ /* Disable Capture */
+ hdcmi->Instance->CR &= ~(DCMI_CR_CAPTURE);
+
+ /* Check if the DCMI capture effectively disabled */
+ do
+ {
+ count-- ;
+ if (count == 0U)
+ {
+ /* Update error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
+
+ /* Change DCMI state */
+ hdcmi->State = HAL_DCMI_STATE_READY;
+
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+ while ((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0U);
+ }
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdcmi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Resume DCMI capture
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_Resume(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Process locked */
+ __HAL_LOCK(hdcmi);
+
+ if (hdcmi->State == HAL_DCMI_STATE_SUSPENDED)
+ {
+ /* Change DCMI state */
+ hdcmi->State = HAL_DCMI_STATE_BUSY;
+
+ /* Disable Capture */
+ hdcmi->Instance->CR |= DCMI_CR_CAPTURE;
+ }
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdcmi);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Handles DCMI interrupt request.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for the DCMI.
+ * @retval None
+ */
+void HAL_DCMI_IRQHandler(DCMI_HandleTypeDef *hdcmi)
+{
+ uint32_t isr_value = READ_REG(hdcmi->Instance->MISR);
+
+ /* Synchronization error interrupt management *******************************/
+ if ((isr_value & DCMI_FLAG_ERRRI) == DCMI_FLAG_ERRRI)
+ {
+ /* Clear the Synchronization error flag */
+ __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_ERRRI);
+
+ /* Update error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_SYNC;
+
+ /* Change DCMI state */
+ hdcmi->State = HAL_DCMI_STATE_ERROR;
+
+ /* Set the synchronization error callback */
+ hdcmi->DMA_Handle->XferAbortCallback = DCMI_DMAError;
+
+ /* Abort the DMA Transfer */
+ (void)HAL_DMA_Abort_IT(hdcmi->DMA_Handle);
+ }
+ /* Overflow interrupt management ********************************************/
+ if ((isr_value & DCMI_FLAG_OVRRI) == DCMI_FLAG_OVRRI)
+ {
+ /* Clear the Overflow flag */
+ __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_OVRRI);
+
+ /* Update error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_OVR;
+
+ /* Change DCMI state */
+ hdcmi->State = HAL_DCMI_STATE_ERROR;
+
+ /* Set the overflow callback */
+ hdcmi->DMA_Handle->XferAbortCallback = DCMI_DMAError;
+
+ /* Abort the DMA Transfer */
+ (void)HAL_DMA_Abort_IT(hdcmi->DMA_Handle);
+ }
+ /* Line Interrupt management ************************************************/
+ if ((isr_value & DCMI_FLAG_LINERI) == DCMI_FLAG_LINERI)
+ {
+ /* Clear the Line interrupt flag */
+ __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_LINERI);
+
+ /* Line interrupt Callback */
+#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
+ /*Call registered DCMI line event callback*/
+ hdcmi->LineEventCallback(hdcmi);
+#else
+ HAL_DCMI_LineEventCallback(hdcmi);
+#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
+ }
+ /* VSYNC interrupt management ***********************************************/
+ if ((isr_value & DCMI_FLAG_VSYNCRI) == DCMI_FLAG_VSYNCRI)
+ {
+ /* Clear the VSYNC flag */
+ __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_VSYNCRI);
+
+ /* VSYNC Callback */
+#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
+ /*Call registered DCMI vsync event callback*/
+ hdcmi->VsyncEventCallback(hdcmi);
+#else
+ HAL_DCMI_VsyncEventCallback(hdcmi);
+#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
+ }
+ /* FRAME interrupt management ***********************************************/
+ if ((isr_value & DCMI_FLAG_FRAMERI) == DCMI_FLAG_FRAMERI)
+ {
+ /* When snapshot mode, disable Vsync, Error and Overrun interrupts */
+ if ((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
+ {
+ /* Disable the Line, Vsync, Error and Overrun interrupts */
+ __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR);
+ }
+
+ /* Disable the Frame interrupt */
+ __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_FRAME);
+
+ /* Clear the End of Frame flag */
+ __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_FRAMERI);
+
+ /* Frame Callback */
+#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
+ /*Call registered DCMI frame event callback*/
+ hdcmi->FrameEventCallback(hdcmi);
+#else
+ HAL_DCMI_FrameEventCallback(hdcmi);
+#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Error DCMI callback.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval None
+ */
+__weak void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdcmi);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DCMI_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Line Event callback.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval None
+ */
+__weak void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdcmi);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DCMI_LineEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief VSYNC Event callback.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval None
+ */
+__weak void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdcmi);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DCMI_VsyncEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Frame Event callback.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval None
+ */
+__weak void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdcmi);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DCMI_FrameEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DCMI_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+[..] This section provides functions allowing to:
+ (+) Configure the CROP feature.
+ (+) Enable/Disable the CROP feature.
+ (+) Set embedded synchronization delimiters unmasks.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the DCMI CROP coordinate.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @param YSize DCMI Line number
+ * @param XSize DCMI Pixel per line
+ * @param X0 DCMI window X offset
+ * @param Y0 DCMI window Y offset
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef *hdcmi, uint32_t X0, uint32_t Y0, uint32_t XSize, uint32_t YSize)
+{
+ /* Process Locked */
+ __HAL_LOCK(hdcmi);
+
+ /* Lock the DCMI peripheral state */
+ hdcmi->State = HAL_DCMI_STATE_BUSY;
+
+ /* Check the parameters */
+ assert_param(IS_DCMI_WINDOW_COORDINATE(X0));
+ assert_param(IS_DCMI_WINDOW_HEIGHT(Y0));
+ assert_param(IS_DCMI_WINDOW_COORDINATE(XSize));
+ assert_param(IS_DCMI_WINDOW_COORDINATE(YSize));
+
+ /* Configure CROP */
+ hdcmi->Instance->CWSIZER = (XSize | (YSize << DCMI_CWSIZE_VLINE_Pos));
+ hdcmi->Instance->CWSTRTR = (X0 | (Y0 << DCMI_CWSTRT_VST_Pos));
+
+ /* Initialize the DCMI state*/
+ hdcmi->State = HAL_DCMI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdcmi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the Crop feature.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_DisableCrop(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Process Locked */
+ __HAL_LOCK(hdcmi);
+
+ /* Lock the DCMI peripheral state */
+ hdcmi->State = HAL_DCMI_STATE_BUSY;
+
+ /* Disable DCMI Crop feature */
+ hdcmi->Instance->CR &= ~(uint32_t)DCMI_CR_CROP;
+
+ /* Change the DCMI state*/
+ hdcmi->State = HAL_DCMI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdcmi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the Crop feature.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_EnableCrop(DCMI_HandleTypeDef *hdcmi)
+{
+ /* Process Locked */
+ __HAL_LOCK(hdcmi);
+
+ /* Lock the DCMI peripheral state */
+ hdcmi->State = HAL_DCMI_STATE_BUSY;
+
+ /* Enable DCMI Crop feature */
+ hdcmi->Instance->CR |= (uint32_t)DCMI_CR_CROP;
+
+ /* Change the DCMI state*/
+ hdcmi->State = HAL_DCMI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdcmi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set embedded synchronization delimiters unmasks.
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @param SyncUnmask pointer to a DCMI_SyncUnmaskTypeDef structure that contains
+ * the embedded synchronization delimiters unmasks.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef *hdcmi, DCMI_SyncUnmaskTypeDef *SyncUnmask)
+{
+ /* Process Locked */
+ __HAL_LOCK(hdcmi);
+
+ /* Lock the DCMI peripheral state */
+ hdcmi->State = HAL_DCMI_STATE_BUSY;
+
+ /* Write DCMI embedded synchronization unmask register */
+ hdcmi->Instance->ESUR = (((uint32_t)SyncUnmask->FrameStartUnmask) | \
+ ((uint32_t)SyncUnmask->LineStartUnmask << DCMI_ESUR_LSU_Pos) | \
+ ((uint32_t)SyncUnmask->LineEndUnmask << DCMI_ESUR_LEU_Pos) | \
+ ((uint32_t)SyncUnmask->FrameEndUnmask << DCMI_ESUR_FEU_Pos));
+
+ /* Change the DCMI state*/
+ hdcmi->State = HAL_DCMI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdcmi);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DCMI_Exported_Functions_Group4 Peripheral State functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Check the DCMI state.
+ (+) Get the specific DCMI error flag.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the DCMI state
+ * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+ * @retval HAL state
+ */
+HAL_DCMI_StateTypeDef HAL_DCMI_GetState(DCMI_HandleTypeDef *hdcmi)
+{
+ return hdcmi->State;
+}
+
+/**
+* @brief Return the DCMI error code
+* @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
+ * the configuration information for DCMI.
+* @retval DCMI Error Code
+*/
+uint32_t HAL_DCMI_GetError(DCMI_HandleTypeDef *hdcmi)
+{
+ return hdcmi->ErrorCode;
+}
+
+#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User DCMI Callback
+ * To be used instead of the weak predefined callback
+ * @param hdcmi DCMI handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DCMI_LINE_EVENT_CB_ID Line Event callback ID
+ * @arg @ref HAL_DCMI_FRAME_EVENT_CB_ID Frame Event callback ID
+ * @arg @ref HAL_DCMI_VSYNC_EVENT_CB_ID Vsync Event callback ID
+ * @arg @ref HAL_DCMI_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_DCMI_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_DCMI_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID, pDCMI_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* update the error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ if (hdcmi->State == HAL_DCMI_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DCMI_FRAME_EVENT_CB_ID :
+ hdcmi->FrameEventCallback = pCallback;
+ break;
+
+ case HAL_DCMI_VSYNC_EVENT_CB_ID :
+ hdcmi->VsyncEventCallback = pCallback;
+ break;
+
+ case HAL_DCMI_LINE_EVENT_CB_ID :
+ hdcmi->LineEventCallback = pCallback;
+ break;
+
+ case HAL_DCMI_ERROR_CB_ID :
+ hdcmi->ErrorCallback = pCallback;
+ break;
+
+ case HAL_DCMI_MSPINIT_CB_ID :
+ hdcmi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_DCMI_MSPDEINIT_CB_ID :
+ hdcmi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hdcmi->State == HAL_DCMI_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DCMI_MSPINIT_CB_ID :
+ hdcmi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_DCMI_MSPDEINIT_CB_ID :
+ hdcmi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* update the error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a DCMI Callback
+ * DCMI callabck is redirected to the weak predefined callback
+ * @param hdcmi DCMI handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DCMI_LINE_EVENT_CB_ID Line Event callback ID
+ * @arg @ref HAL_DCMI_FRAME_EVENT_CB_ID Frame Event callback ID
+ * @arg @ref HAL_DCMI_VSYNC_EVENT_CB_ID Vsync Event callback ID
+ * @arg @ref HAL_DCMI_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_DCMI_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_DCMI_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hdcmi->State == HAL_DCMI_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DCMI_FRAME_EVENT_CB_ID :
+ hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback */
+ break;
+
+ case HAL_DCMI_VSYNC_EVENT_CB_ID :
+ hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback */
+ break;
+
+ case HAL_DCMI_LINE_EVENT_CB_ID :
+ hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback; /* Legacy weak LineEventCallback */
+ break;
+
+ case HAL_DCMI_ERROR_CB_ID :
+ hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_DCMI_MSPINIT_CB_ID :
+ hdcmi->MspInitCallback = HAL_DCMI_MspInit;
+ break;
+
+ case HAL_DCMI_MSPDEINIT_CB_ID :
+ hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
+ break;
+
+ default :
+ /* update the error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hdcmi->State == HAL_DCMI_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DCMI_MSPINIT_CB_ID :
+ hdcmi->MspInitCallback = HAL_DCMI_MspInit;
+ break;
+
+ case HAL_DCMI_MSPDEINIT_CB_ID :
+ hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
+ break;
+
+ default :
+ /* update the error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup DCMI_Private_Functions DCMI Private Functions
+ * @{
+ */
+/**
+ * @brief DMA conversion complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tmp ;
+
+ DCMI_HandleTypeDef *hdcmi = (DCMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdcmi->XferCount != 0U)
+ {
+ /* Update memory 0 address location */
+ tmp = ((((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->CR) & DMA_SxCR_CT);
+ if (((hdcmi->XferCount % 2U) == 0U) && (tmp != 0U))
+ {
+ tmp = ((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->M0AR;
+ (void)HAL_DMAEx_ChangeMemory(hdcmi->DMA_Handle, (tmp + (8U * hdcmi->XferSize)), MEMORY0);
+ hdcmi->XferCount--;
+ }
+ /* Update memory 1 address location */
+ else if ((((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->CR & DMA_SxCR_CT) == 0U)
+ {
+ tmp = ((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->M1AR;
+ (void)HAL_DMAEx_ChangeMemory(hdcmi->DMA_Handle, (tmp + (8U * hdcmi->XferSize)), MEMORY1);
+ hdcmi->XferCount--;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ /* Update memory 0 address location */
+ else if ((((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->CR & DMA_SxCR_CT) != 0U)
+ {
+ ((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->M0AR = hdcmi->pBuffPtr;
+ }
+ /* Update memory 1 address location */
+ else if ((((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->CR & DMA_SxCR_CT) == 0U)
+ {
+ tmp = hdcmi->pBuffPtr;
+ ((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->M1AR = (tmp + (4U * hdcmi->XferSize));
+ hdcmi->XferCount = hdcmi->XferTransferNumber;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Check if the frame is transferred */
+ if (hdcmi->XferCount == hdcmi->XferTransferNumber)
+ {
+ /* Enable the Frame interrupt */
+ __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_FRAME);
+
+ /* When snapshot mode, set dcmi state to ready */
+ if ((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
+ {
+ hdcmi->State = HAL_DCMI_STATE_READY;
+ }
+ }
+}
+
+/**
+ * @brief DMA error callback
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void DCMI_DMAError(DMA_HandleTypeDef *hdma)
+{
+ DCMI_HandleTypeDef *hdcmi = (DCMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdcmi->DMA_Handle->ErrorCode != HAL_DMA_ERROR_FE)
+ {
+ /* Initialize the DCMI state*/
+ hdcmi->State = HAL_DCMI_STATE_READY;
+
+ /* Set DCMI Error Code */
+ hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
+ }
+
+ /* DCMI error Callback */
+#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
+ /*Call registered DCMI error callback*/
+ hdcmi->ErrorCallback(hdcmi);
+#else
+ HAL_DCMI_ErrorCallback(hdcmi);
+#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+#endif /* DCMI */
+#endif /* HAL_DCMI_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dfsdm.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dfsdm.c
new file mode 100644
index 0000000000..220e07a960
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dfsdm.c
@@ -0,0 +1,3798 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dfsdm.c
+ * @author MCD Application Team
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Digital Filter for Sigma-Delta Modulators
+ * (DFSDM) peripherals:
+ * + Initialization and configuration of channels and filters
+ * + Regular channels configuration
+ * + Injected channels configuration
+ * + Regular/Injected Channels DMA Configuration
+ * + Interrupts and flags management
+ * + Analog watchdog feature
+ * + Short-circuit detector feature
+ * + Extremes detector feature
+ * + Clock absence detector feature
+ * + Break generation on analog watchdog or short-circuit event
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ *** Channel initialization ***
+ ==============================
+ [..]
+ (#) User has first to initialize channels (before filters initialization).
+ (#) As prerequisite, fill in the HAL_DFSDM_ChannelMspInit() :
+ (++) Enable DFSDMz clock interface with __HAL_RCC_DFSDMz_CLK_ENABLE().
+ (++) Enable the clocks for the DFSDMz GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE().
+ (++) Configure these DFSDMz pins in alternate mode using HAL_GPIO_Init().
+ (++) If interrupt mode is used, enable and configure DFSDMz_FLT0 global
+ interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
+ (#) Configure the output clock, input, serial interface, analog watchdog,
+ offset and data right bit shift parameters for this channel using the
+ HAL_DFSDM_ChannelInit() function.
+
+ *** Channel clock absence detector ***
+ ======================================
+ [..]
+ (#) Start clock absence detector using HAL_DFSDM_ChannelCkabStart() or
+ HAL_DFSDM_ChannelCkabStart_IT().
+ (#) In polling mode, use HAL_DFSDM_ChannelPollForCkab() to detect the clock
+ absence.
+ (#) In interrupt mode, HAL_DFSDM_ChannelCkabCallback() will be called if
+ clock absence is detected.
+ (#) Stop clock absence detector using HAL_DFSDM_ChannelCkabStop() or
+ HAL_DFSDM_ChannelCkabStop_IT().
+ (#) Please note that the same mode (polling or interrupt) has to be used
+ for all channels because the channels are sharing the same interrupt.
+ (#) Please note also that in interrupt mode, if clock absence detector is
+ stopped for one channel, interrupt will be disabled for all channels.
+
+ *** Channel short circuit detector ***
+ ======================================
+ [..]
+ (#) Start short circuit detector using HAL_DFSDM_ChannelScdStart() or
+ or HAL_DFSDM_ChannelScdStart_IT().
+ (#) In polling mode, use HAL_DFSDM_ChannelPollForScd() to detect short
+ circuit.
+ (#) In interrupt mode, HAL_DFSDM_ChannelScdCallback() will be called if
+ short circuit is detected.
+ (#) Stop short circuit detector using HAL_DFSDM_ChannelScdStop() or
+ or HAL_DFSDM_ChannelScdStop_IT().
+ (#) Please note that the same mode (polling or interrupt) has to be used
+ for all channels because the channels are sharing the same interrupt.
+ (#) Please note also that in interrupt mode, if short circuit detector is
+ stopped for one channel, interrupt will be disabled for all channels.
+
+ *** Channel analog watchdog value ***
+ =====================================
+ [..]
+ (#) Get analog watchdog filter value of a channel using
+ HAL_DFSDM_ChannelGetAwdValue().
+
+ *** Channel offset value ***
+ =====================================
+ [..]
+ (#) Modify offset value of a channel using HAL_DFSDM_ChannelModifyOffset().
+
+ *** Filter initialization ***
+ =============================
+ [..]
+ (#) After channel initialization, user has to init filters.
+ (#) As prerequisite, fill in the HAL_DFSDM_FilterMspInit() :
+ (++) If interrupt mode is used , enable and configure DFSDMz_FLTx global
+ interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
+ Please note that DFSDMz_FLT0 global interrupt could be already
+ enabled if interrupt is used for channel.
+ (++) If DMA mode is used, configure DMA with HAL_DMA_Init() and link it
+ with DFSDMz filter handle using __HAL_LINKDMA().
+ (#) Configure the regular conversion, injected conversion and filter
+ parameters for this filter using the HAL_DFSDM_FilterInit() function.
+
+ *** Filter regular channel conversion ***
+ =========================================
+ [..]
+ (#) Select regular channel and enable/disable continuous mode using
+ HAL_DFSDM_FilterConfigRegChannel().
+ (#) Start regular conversion using HAL_DFSDM_FilterRegularStart(),
+ HAL_DFSDM_FilterRegularStart_IT(), HAL_DFSDM_FilterRegularStart_DMA() or
+ HAL_DFSDM_FilterRegularMsbStart_DMA().
+ (#) In polling mode, use HAL_DFSDM_FilterPollForRegConversion() to detect
+ the end of regular conversion.
+ (#) In interrupt mode, HAL_DFSDM_FilterRegConvCpltCallback() will be called
+ at the end of regular conversion.
+ (#) Get value of regular conversion and corresponding channel using
+ HAL_DFSDM_FilterGetRegularValue().
+ (#) In DMA mode, HAL_DFSDM_FilterRegConvHalfCpltCallback() and
+ HAL_DFSDM_FilterRegConvCpltCallback() will be called respectively at the
+ half transfer and at the transfer complete. Please note that
+ HAL_DFSDM_FilterRegConvHalfCpltCallback() will be called only in DMA
+ circular mode.
+ (#) Stop regular conversion using HAL_DFSDM_FilterRegularStop(),
+ HAL_DFSDM_FilterRegularStop_IT() or HAL_DFSDM_FilterRegularStop_DMA().
+
+ *** Filter injected channels conversion ***
+ ===========================================
+ [..]
+ (#) Select injected channels using HAL_DFSDM_FilterConfigInjChannel().
+ (#) Start injected conversion using HAL_DFSDM_FilterInjectedStart(),
+ HAL_DFSDM_FilterInjectedStart_IT(), HAL_DFSDM_FilterInjectedStart_DMA() or
+ HAL_DFSDM_FilterInjectedMsbStart_DMA().
+ (#) In polling mode, use HAL_DFSDM_FilterPollForInjConversion() to detect
+ the end of injected conversion.
+ (#) In interrupt mode, HAL_DFSDM_FilterInjConvCpltCallback() will be called
+ at the end of injected conversion.
+ (#) Get value of injected conversion and corresponding channel using
+ HAL_DFSDM_FilterGetInjectedValue().
+ (#) In DMA mode, HAL_DFSDM_FilterInjConvHalfCpltCallback() and
+ HAL_DFSDM_FilterInjConvCpltCallback() will be called respectively at the
+ half transfer and at the transfer complete. Please note that
+ HAL_DFSDM_FilterInjConvCpltCallback() will be called only in DMA
+ circular mode.
+ (#) Stop injected conversion using HAL_DFSDM_FilterInjectedStop(),
+ HAL_DFSDM_FilterInjectedStop_IT() or HAL_DFSDM_FilterInjectedStop_DMA().
+
+ *** Filter analog watchdog ***
+ ==============================
+ [..]
+ (#) Start filter analog watchdog using HAL_DFSDM_FilterAwdStart_IT().
+ (#) HAL_DFSDM_FilterAwdCallback() will be called if analog watchdog occurs.
+ (#) Stop filter analog watchdog using HAL_DFSDM_FilterAwdStop_IT().
+
+ *** Filter extreme detector ***
+ ===============================
+ [..]
+ (#) Start filter extreme detector using HAL_DFSDM_FilterExdStart().
+ (#) Get extreme detector maximum value using HAL_DFSDM_FilterGetExdMaxValue().
+ (#) Get extreme detector minimum value using HAL_DFSDM_FilterGetExdMinValue().
+ (#) Start filter extreme detector using HAL_DFSDM_FilterExdStop().
+
+ *** Filter conversion time ***
+ ==============================
+ [..]
+ (#) Get conversion time value using HAL_DFSDM_FilterGetConvTimeValue().
+
+ *** Callback registration ***
+ =============================
+ [..]
+ The compilation define USE_HAL_DFSDM_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use functions HAL_DFSDM_Channel_RegisterCallback(),
+ HAL_DFSDM_Filter_RegisterCallback() or
+ HAL_DFSDM_Filter_RegisterAwdCallback() to register a user callback.
+
+ [..]
+ Function HAL_DFSDM_Channel_RegisterCallback() allows to register
+ following callbacks:
+ (+) CkabCallback : DFSDM channel clock absence detection callback.
+ (+) ScdCallback : DFSDM channel short circuit detection callback.
+ (+) MspInitCallback : DFSDM channel MSP init callback.
+ (+) MspDeInitCallback : DFSDM channel MSP de-init callback.
+ [..]
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Function HAL_DFSDM_Filter_RegisterCallback() allows to register
+ following callbacks:
+ (+) RegConvCpltCallback : DFSDM filter regular conversion complete callback.
+ (+) RegConvHalfCpltCallback : DFSDM filter half regular conversion complete callback.
+ (+) InjConvCpltCallback : DFSDM filter injected conversion complete callback.
+ (+) InjConvHalfCpltCallback : DFSDM filter half injected conversion complete callback.
+ (+) ErrorCallback : DFSDM filter error callback.
+ (+) MspInitCallback : DFSDM filter MSP init callback.
+ (+) MspDeInitCallback : DFSDM filter MSP de-init callback.
+ [..]
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ For specific DFSDM filter analog watchdog callback use dedicated register callback:
+ HAL_DFSDM_Filter_RegisterAwdCallback().
+
+ [..]
+ Use functions HAL_DFSDM_Channel_UnRegisterCallback() or
+ HAL_DFSDM_Filter_UnRegisterCallback() to reset a callback to the default
+ weak function.
+
+ [..]
+ HAL_DFSDM_Channel_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ [..]
+ This function allows to reset following callbacks:
+ (+) CkabCallback : DFSDM channel clock absence detection callback.
+ (+) ScdCallback : DFSDM channel short circuit detection callback.
+ (+) MspInitCallback : DFSDM channel MSP init callback.
+ (+) MspDeInitCallback : DFSDM channel MSP de-init callback.
+
+ [..]
+ HAL_DFSDM_Filter_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ [..]
+ This function allows to reset following callbacks:
+ (+) RegConvCpltCallback : DFSDM filter regular conversion complete callback.
+ (+) RegConvHalfCpltCallback : DFSDM filter half regular conversion complete callback.
+ (+) InjConvCpltCallback : DFSDM filter injected conversion complete callback.
+ (+) InjConvHalfCpltCallback : DFSDM filter half injected conversion complete callback.
+ (+) ErrorCallback : DFSDM filter error callback.
+ (+) MspInitCallback : DFSDM filter MSP init callback.
+ (+) MspDeInitCallback : DFSDM filter MSP de-init callback.
+
+ [..]
+ For specific DFSDM filter analog watchdog callback use dedicated unregister callback:
+ HAL_DFSDM_Filter_UnRegisterAwdCallback().
+
+ [..]
+ By default, after the call of init function and if the state is RESET
+ all callbacks are reset to the corresponding legacy weak functions:
+ examples HAL_DFSDM_ChannelScdCallback(), HAL_DFSDM_FilterErrorCallback().
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak functions in the init and de-init only when these
+ callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the init and de-init 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/de-init.
+ In that case first register the MspInit/MspDeInit user callbacks using
+ HAL_DFSDM_Channel_RegisterCallback() or
+ HAL_DFSDM_Filter_RegisterCallback() before calling init or de-init function.
+
+ [..]
+ When The compilation define USE_HAL_DFSDM_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#ifdef HAL_DFSDM_MODULE_ENABLED
+
+/** @defgroup DFSDM DFSDM
+ * @brief DFSDM HAL driver module
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup DFSDM_Private_Define DFSDM Private Define
+ * @{
+ */
+#define DFSDM_FLTCR1_MSB_RCH_OFFSET 8
+#define DFSDM_MSB_MASK 0xFFFF0000U
+#define DFSDM_LSB_MASK 0x0000FFFFU
+#define DFSDM_CKAB_TIMEOUT 5000U
+#define DFSDM1_CHANNEL_NUMBER 8U
+#if defined(DFSDM2_Channel0)
+#define DFSDM2_CHANNEL_NUMBER 2U
+#endif /* DFSDM2_Channel0 */
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup DFSDM_Private_Variables DFSDM Private Variables
+ * @{
+ */
+static __IO uint32_t v_dfsdm1ChannelCounter = 0;
+static DFSDM_Channel_HandleTypeDef *a_dfsdm1ChannelHandle[DFSDM1_CHANNEL_NUMBER] = {NULL};
+#if defined(DFSDM2_Channel0)
+static __IO uint32_t v_dfsdm2ChannelCounter = 0;
+static DFSDM_Channel_HandleTypeDef *a_dfsdm2ChannelHandle[DFSDM2_CHANNEL_NUMBER] = {NULL};
+#endif /* DFSDM2_Channel0 */
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup DFSDM_Private_Functions DFSDM Private Functions
+ * @{
+ */
+static uint32_t DFSDM_GetInjChannelsNbr(uint32_t Channels);
+static uint32_t DFSDM_GetChannelFromInstance(const DFSDM_Channel_TypeDef *Instance);
+static void DFSDM_RegConvStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter);
+static void DFSDM_RegConvStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter);
+static void DFSDM_InjConvStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter);
+static void DFSDM_InjConvStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter);
+static void DFSDM_DMARegularHalfConvCplt(DMA_HandleTypeDef *hdma);
+static void DFSDM_DMARegularConvCplt(DMA_HandleTypeDef *hdma);
+static void DFSDM_DMAInjectedHalfConvCplt(DMA_HandleTypeDef *hdma);
+static void DFSDM_DMAInjectedConvCplt(DMA_HandleTypeDef *hdma);
+static void DFSDM_DMAError(DMA_HandleTypeDef *hdma);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup DFSDM_Exported_Functions DFSDM Exported Functions
+ * @{
+ */
+
+/** @defgroup DFSDM_Exported_Functions_Group1_Channel Channel initialization and de-initialization functions
+ * @brief Channel initialization and de-initialization functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Channel initialization and de-initialization functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the DFSDM channel.
+ (+) De-initialize the DFSDM channel.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the DFSDM channel according to the specified parameters
+ * in the DFSDM_ChannelInitTypeDef structure and initialize the associated handle.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ __IO uint32_t *channelCounterPtr;
+ DFSDM_Channel_HandleTypeDef **channelHandleTable;
+ DFSDM_Channel_TypeDef *channel0Instance;
+
+ /* Check DFSDM Channel handle */
+ if(hdfsdm_channel == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+ assert_param(IS_FUNCTIONAL_STATE(hdfsdm_channel->Init.OutputClock.Activation));
+ assert_param(IS_DFSDM_CHANNEL_INPUT(hdfsdm_channel->Init.Input.Multiplexer));
+ assert_param(IS_DFSDM_CHANNEL_DATA_PACKING(hdfsdm_channel->Init.Input.DataPacking));
+ assert_param(IS_DFSDM_CHANNEL_INPUT_PINS(hdfsdm_channel->Init.Input.Pins));
+ assert_param(IS_DFSDM_CHANNEL_SERIAL_INTERFACE_TYPE(hdfsdm_channel->Init.SerialInterface.Type));
+ assert_param(IS_DFSDM_CHANNEL_SPI_CLOCK(hdfsdm_channel->Init.SerialInterface.SpiClock));
+ assert_param(IS_DFSDM_CHANNEL_FILTER_ORDER(hdfsdm_channel->Init.Awd.FilterOrder));
+ assert_param(IS_DFSDM_CHANNEL_FILTER_OVS_RATIO(hdfsdm_channel->Init.Awd.Oversampling));
+ assert_param(IS_DFSDM_CHANNEL_OFFSET(hdfsdm_channel->Init.Offset));
+ assert_param(IS_DFSDM_CHANNEL_RIGHT_BIT_SHIFT(hdfsdm_channel->Init.RightBitShift));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ channelCounterPtr = &v_dfsdm1ChannelCounter;
+ channelHandleTable = a_dfsdm1ChannelHandle;
+ channel0Instance = DFSDM1_Channel0;
+ }
+ else
+ {
+ channelCounterPtr = &v_dfsdm2ChannelCounter;
+ channelHandleTable = a_dfsdm2ChannelHandle;
+ channel0Instance = DFSDM2_Channel0;
+ }
+#else /* DFSDM2_Channel0 */
+ channelCounterPtr = &v_dfsdm1ChannelCounter;
+ channelHandleTable = a_dfsdm1ChannelHandle;
+ channel0Instance = DFSDM1_Channel0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check that channel has not been already initialized */
+ if (channelHandleTable[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] != NULL)
+ {
+ return HAL_ERROR;
+ }
+
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ /* Reset callback pointers to the weak predefined callbacks */
+ hdfsdm_channel->CkabCallback = HAL_DFSDM_ChannelCkabCallback;
+ hdfsdm_channel->ScdCallback = HAL_DFSDM_ChannelScdCallback;
+
+ /* Call MSP init function */
+ if(hdfsdm_channel->MspInitCallback == NULL)
+ {
+ hdfsdm_channel->MspInitCallback = HAL_DFSDM_ChannelMspInit;
+ }
+ hdfsdm_channel->MspInitCallback(hdfsdm_channel);
+#else
+ /* Call MSP init function */
+ HAL_DFSDM_ChannelMspInit(hdfsdm_channel);
+#endif
+
+ /* Update the channel counter */
+ (*channelCounterPtr)++;
+
+ /* Configure output serial clock and enable global DFSDM interface only for first channel */
+ if(*channelCounterPtr == 1U)
+ {
+ assert_param(IS_DFSDM_CHANNEL_OUTPUT_CLOCK(hdfsdm_channel->Init.OutputClock.Selection));
+ /* Set the output serial clock source */
+ channel0Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKOUTSRC);
+ channel0Instance->CHCFGR1 |= hdfsdm_channel->Init.OutputClock.Selection;
+
+ /* Reset clock divider */
+ channel0Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKOUTDIV);
+ if(hdfsdm_channel->Init.OutputClock.Activation == ENABLE)
+ {
+ assert_param(IS_DFSDM_CHANNEL_OUTPUT_CLOCK_DIVIDER(hdfsdm_channel->Init.OutputClock.Divider));
+ /* Set the output clock divider */
+ channel0Instance->CHCFGR1 |= (uint32_t)((hdfsdm_channel->Init.OutputClock.Divider - 1U) <<
+ DFSDM_CHCFGR1_CKOUTDIV_Pos);
+ }
+
+ /* enable the DFSDM global interface */
+ channel0Instance->CHCFGR1 |= DFSDM_CHCFGR1_DFSDMEN;
+ }
+
+ /* Set channel input parameters */
+ hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_DATPACK | DFSDM_CHCFGR1_DATMPX |
+ DFSDM_CHCFGR1_CHINSEL);
+ hdfsdm_channel->Instance->CHCFGR1 |= (hdfsdm_channel->Init.Input.Multiplexer |
+ hdfsdm_channel->Init.Input.DataPacking |
+ hdfsdm_channel->Init.Input.Pins);
+
+ /* Set serial interface parameters */
+ hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_SITP | DFSDM_CHCFGR1_SPICKSEL);
+ hdfsdm_channel->Instance->CHCFGR1 |= (hdfsdm_channel->Init.SerialInterface.Type |
+ hdfsdm_channel->Init.SerialInterface.SpiClock);
+
+ /* Set analog watchdog parameters */
+ hdfsdm_channel->Instance->CHAWSCDR &= ~(DFSDM_CHAWSCDR_AWFORD | DFSDM_CHAWSCDR_AWFOSR);
+ hdfsdm_channel->Instance->CHAWSCDR |= (hdfsdm_channel->Init.Awd.FilterOrder |
+ ((hdfsdm_channel->Init.Awd.Oversampling - 1U) << DFSDM_CHAWSCDR_AWFOSR_Pos));
+
+ /* Set channel offset and right bit shift */
+ hdfsdm_channel->Instance->CHCFGR2 &= ~(DFSDM_CHCFGR2_OFFSET | DFSDM_CHCFGR2_DTRBS);
+ hdfsdm_channel->Instance->CHCFGR2 |= (((uint32_t) hdfsdm_channel->Init.Offset << DFSDM_CHCFGR2_OFFSET_Pos) |
+ (hdfsdm_channel->Init.RightBitShift << DFSDM_CHCFGR2_DTRBS_Pos));
+
+ /* Enable DFSDM channel */
+ hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_CHEN;
+
+ /* Set DFSDM Channel to ready state */
+ hdfsdm_channel->State = HAL_DFSDM_CHANNEL_STATE_READY;
+
+ /* Store channel handle in DFSDM channel handle table */
+ channelHandleTable[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] = hdfsdm_channel;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief De-initialize the DFSDM channel.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ __IO uint32_t *channelCounterPtr;
+ DFSDM_Channel_HandleTypeDef **channelHandleTable;
+ DFSDM_Channel_TypeDef *channel0Instance;
+
+ /* Check DFSDM Channel handle */
+ if(hdfsdm_channel == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ channelCounterPtr = &v_dfsdm1ChannelCounter;
+ channelHandleTable = a_dfsdm1ChannelHandle;
+ channel0Instance = DFSDM1_Channel0;
+ }
+ else
+ {
+ channelCounterPtr = &v_dfsdm2ChannelCounter;
+ channelHandleTable = a_dfsdm2ChannelHandle;
+ channel0Instance = DFSDM2_Channel0;
+ }
+#else /* DFSDM2_Channel0 */
+ channelCounterPtr = &v_dfsdm1ChannelCounter;
+ channelHandleTable = a_dfsdm1ChannelHandle;
+ channel0Instance = DFSDM1_Channel0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check that channel has not been already deinitialized */
+ if (channelHandleTable[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the DFSDM channel */
+ hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CHEN);
+
+ /* Update the channel counter */
+ (*channelCounterPtr)--;
+
+ /* Disable global DFSDM at deinit of last channel */
+ if (*channelCounterPtr == 0U)
+ {
+ channel0Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_DFSDMEN);
+ }
+
+ /* Call MSP deinit function */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ if(hdfsdm_channel->MspDeInitCallback == NULL)
+ {
+ hdfsdm_channel->MspDeInitCallback = HAL_DFSDM_ChannelMspDeInit;
+ }
+ hdfsdm_channel->MspDeInitCallback(hdfsdm_channel);
+#else
+ HAL_DFSDM_ChannelMspDeInit(hdfsdm_channel);
+#endif
+
+ /* Set DFSDM Channel in reset state */
+ hdfsdm_channel->State = HAL_DFSDM_CHANNEL_STATE_RESET;
+
+ /* Reset channel handle in DFSDM channel handle table */
+ channelHandleTable[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] = (DFSDM_Channel_HandleTypeDef *) NULL;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the DFSDM channel MSP.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_channel);
+
+ /* NOTE : This function should not be modified, when the function is needed,
+ the HAL_DFSDM_ChannelMspInit could be implemented in the user file.
+ */
+}
+
+/**
+ * @brief De-initialize the DFSDM channel MSP.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_channel);
+
+ /* NOTE : This function should not be modified, when the function is needed,
+ the HAL_DFSDM_ChannelMspDeInit could be implemented in the user file.
+ */
+}
+
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a user DFSDM channel callback
+ * to be used instead of the weak predefined callback.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @param CallbackID ID of the callback to be registered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DFSDM_CHANNEL_CKAB_CB_ID clock absence detection callback ID.
+ * @arg @ref HAL_DFSDM_CHANNEL_SCD_CB_ID short circuit detection callback ID.
+ * @arg @ref HAL_DFSDM_CHANNEL_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @param pCallback pointer to the callback function.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_Channel_RegisterCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel,
+ HAL_DFSDM_Channel_CallbackIDTypeDef CallbackID,
+ pDFSDM_Channel_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ if(HAL_DFSDM_CHANNEL_STATE_READY == hdfsdm_channel->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DFSDM_CHANNEL_CKAB_CB_ID :
+ hdfsdm_channel->CkabCallback = pCallback;
+ break;
+ case HAL_DFSDM_CHANNEL_SCD_CB_ID :
+ hdfsdm_channel->ScdCallback = pCallback;
+ break;
+ case HAL_DFSDM_CHANNEL_MSPINIT_CB_ID :
+ hdfsdm_channel->MspInitCallback = pCallback;
+ break;
+ case HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID :
+ hdfsdm_channel->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_DFSDM_CHANNEL_STATE_RESET == hdfsdm_channel->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DFSDM_CHANNEL_MSPINIT_CB_ID :
+ hdfsdm_channel->MspInitCallback = pCallback;
+ break;
+ case HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID :
+ hdfsdm_channel->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Unregister a user DFSDM channel callback.
+ * DFSDM channel callback is redirected to the weak predefined callback.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @param CallbackID ID of the callback to be unregistered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DFSDM_CHANNEL_CKAB_CB_ID clock absence detection callback ID.
+ * @arg @ref HAL_DFSDM_CHANNEL_SCD_CB_ID short circuit detection callback ID.
+ * @arg @ref HAL_DFSDM_CHANNEL_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_Channel_UnRegisterCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel,
+ HAL_DFSDM_Channel_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(HAL_DFSDM_CHANNEL_STATE_READY == hdfsdm_channel->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DFSDM_CHANNEL_CKAB_CB_ID :
+ hdfsdm_channel->CkabCallback = HAL_DFSDM_ChannelCkabCallback;
+ break;
+ case HAL_DFSDM_CHANNEL_SCD_CB_ID :
+ hdfsdm_channel->ScdCallback = HAL_DFSDM_ChannelScdCallback;
+ break;
+ case HAL_DFSDM_CHANNEL_MSPINIT_CB_ID :
+ hdfsdm_channel->MspInitCallback = HAL_DFSDM_ChannelMspInit;
+ break;
+ case HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID :
+ hdfsdm_channel->MspDeInitCallback = HAL_DFSDM_ChannelMspDeInit;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_DFSDM_CHANNEL_STATE_RESET == hdfsdm_channel->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DFSDM_CHANNEL_MSPINIT_CB_ID :
+ hdfsdm_channel->MspInitCallback = HAL_DFSDM_ChannelMspInit;
+ break;
+ case HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID :
+ hdfsdm_channel->MspDeInitCallback = HAL_DFSDM_ChannelMspDeInit;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ return status;
+}
+#endif /* USE_HAL_DFSDM_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup DFSDM_Exported_Functions_Group2_Channel Channel operation functions
+ * @brief Channel operation functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Channel operation functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Manage clock absence detector feature.
+ (+) Manage short circuit detector feature.
+ (+) Get analog watchdog value.
+ (+) Modify offset value.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function allows to start clock absence detection in polling mode.
+ * @note Same mode has to be used for all channels.
+ * @note If clock is not available on this channel during 5 seconds,
+ * clock absence detection will not be activated and function
+ * will return HAL_TIMEOUT error.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStart(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t channel;
+ uint32_t tickstart;
+ DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Get channel number from channel instance */
+ channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance);
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Clear clock absence flag */
+ while ((((filter0Instance->FLTISR & DFSDM_FLTISR_CKABF) >> (DFSDM_FLTISR_CKABF_Pos + channel)) & 1U) != 0U)
+ {
+ filter0Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRCKABF_Pos + channel));
+
+ /* Check the Timeout */
+ if((HAL_GetTick()-tickstart) > DFSDM_CKAB_TIMEOUT)
+ {
+ /* Set timeout status */
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Start clock absence detection */
+ hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_CKABEN;
+ }
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to poll for the clock absence detection.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @param Timeout Timeout value in milliseconds.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelPollForCkab(DFSDM_Channel_HandleTypeDef *hdfsdm_channel,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t channel;
+ DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Get channel number from channel instance */
+ channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance);
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait clock absence detection */
+ while ((((filter0Instance->FLTISR & DFSDM_FLTISR_CKABF) >> (DFSDM_FLTISR_CKABF_Pos + channel)) & 1U) == 0U)
+ {
+ /* Check the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Return timeout status */
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear clock absence detection flag */
+ filter0Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRCKABF_Pos + channel));
+
+ /* Return function status */
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief This function allows to stop clock absence detection in polling mode.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStop(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t channel;
+ DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop clock absence detection */
+ hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKABEN);
+
+ /* Clear clock absence flag */
+ channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance);
+ filter0Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRCKABF_Pos + channel));
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start clock absence detection in interrupt mode.
+ * @note Same mode has to be used for all channels.
+ * @note If clock is not available on this channel during 5 seconds,
+ * clock absence detection will not be activated and function
+ * will return HAL_TIMEOUT error.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStart_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t channel;
+ uint32_t tickstart;
+ DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Get channel number from channel instance */
+ channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance);
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Clear clock absence flag */
+ while ((((filter0Instance->FLTISR & DFSDM_FLTISR_CKABF) >> (DFSDM_FLTISR_CKABF_Pos + channel)) & 1U) != 0U)
+ {
+ filter0Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRCKABF_Pos + channel));
+
+ /* Check the Timeout */
+ if((HAL_GetTick()-tickstart) > DFSDM_CKAB_TIMEOUT)
+ {
+ /* Set timeout status */
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Activate clock absence detection interrupt */
+ filter0Instance->FLTCR2 |= DFSDM_FLTCR2_CKABIE;
+
+ /* Start clock absence detection */
+ hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_CKABEN;
+ }
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Clock absence detection callback.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_ChannelCkabCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_channel);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DFSDM_ChannelCkabCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief This function allows to stop clock absence detection in interrupt mode.
+ * @note Interrupt will be disabled for all channels
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStop_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t channel;
+ DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop clock absence detection */
+ hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKABEN);
+
+ /* Clear clock absence flag */
+ channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance);
+ filter0Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRCKABF_Pos + channel));
+
+ /* Disable clock absence detection interrupt */
+ filter0Instance->FLTCR2 &= ~(DFSDM_FLTCR2_CKABIE);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start short circuit detection in polling mode.
+ * @note Same mode has to be used for all channels
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @param Threshold Short circuit detector threshold.
+ * This parameter must be a number between Min_Data = 0 and Max_Data = 255.
+ * @param BreakSignal Break signals assigned to short circuit event.
+ * This parameter can be a values combination of @ref DFSDM_BreakSignals.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelScdStart(DFSDM_Channel_HandleTypeDef *hdfsdm_channel,
+ uint32_t Threshold,
+ uint32_t BreakSignal)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+ assert_param(IS_DFSDM_CHANNEL_SCD_THRESHOLD(Threshold));
+ assert_param(IS_DFSDM_BREAK_SIGNALS(BreakSignal));
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Configure threshold and break signals */
+ hdfsdm_channel->Instance->CHAWSCDR &= ~(DFSDM_CHAWSCDR_BKSCD | DFSDM_CHAWSCDR_SCDT);
+ hdfsdm_channel->Instance->CHAWSCDR |= ((BreakSignal << DFSDM_CHAWSCDR_BKSCD_Pos) | \
+ Threshold);
+
+ /* Start short circuit detection */
+ hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_SCDEN;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to poll for the short circuit detection.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @param Timeout Timeout value in milliseconds.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelPollForScd(DFSDM_Channel_HandleTypeDef *hdfsdm_channel,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t channel;
+ DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Get channel number from channel instance */
+ channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance);
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait short circuit detection */
+ while (((filter0Instance->FLTISR & DFSDM_FLTISR_SCDF) >> (DFSDM_FLTISR_SCDF_Pos + channel)) == 0U)
+ {
+ /* Check the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Return timeout status */
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear short circuit detection flag */
+ filter0Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRSCDF_Pos + channel));
+
+ /* Return function status */
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief This function allows to stop short circuit detection in polling mode.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelScdStop(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t channel;
+ DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop short circuit detection */
+ hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_SCDEN);
+
+ /* Clear short circuit detection flag */
+ channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance);
+ filter0Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRSCDF_Pos + channel));
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start short circuit detection in interrupt mode.
+ * @note Same mode has to be used for all channels
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @param Threshold Short circuit detector threshold.
+ * This parameter must be a number between Min_Data = 0 and Max_Data = 255.
+ * @param BreakSignal Break signals assigned to short circuit event.
+ * This parameter can be a values combination of @ref DFSDM_BreakSignals.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelScdStart_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel,
+ uint32_t Threshold,
+ uint32_t BreakSignal)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+ assert_param(IS_DFSDM_CHANNEL_SCD_THRESHOLD(Threshold));
+ assert_param(IS_DFSDM_BREAK_SIGNALS(BreakSignal));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Activate short circuit detection interrupt */
+ filter0Instance->FLTCR2 |= DFSDM_FLTCR2_SCDIE;
+
+ /* Configure threshold and break signals */
+ hdfsdm_channel->Instance->CHAWSCDR &= ~(DFSDM_CHAWSCDR_BKSCD | DFSDM_CHAWSCDR_SCDT);
+ hdfsdm_channel->Instance->CHAWSCDR |= ((BreakSignal << DFSDM_CHAWSCDR_BKSCD_Pos) | \
+ Threshold);
+
+ /* Start short circuit detection */
+ hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_SCDEN;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Short circuit detection callback.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_ChannelScdCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_channel);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DFSDM_ChannelScdCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief This function allows to stop short circuit detection in interrupt mode.
+ * @note Interrupt will be disabled for all channels
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelScdStop_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t channel;
+ DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop short circuit detection */
+ hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_SCDEN);
+
+ /* Clear short circuit detection flag */
+ channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance);
+ filter0Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRSCDF_Pos + channel));
+
+ /* Disable short circuit detection interrupt */
+ filter0Instance->FLTCR2 &= ~(DFSDM_FLTCR2_SCDIE);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to get channel analog watchdog value.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval Channel analog watchdog value.
+ */
+int16_t HAL_DFSDM_ChannelGetAwdValue(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ return (int16_t) hdfsdm_channel->Instance->CHWDATAR;
+}
+
+/**
+ * @brief This function allows to modify channel offset value.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @param Offset DFSDM channel offset.
+ * This parameter must be a number between Min_Data = -8388608 and Max_Data = 8388607.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_ChannelModifyOffset(DFSDM_Channel_HandleTypeDef *hdfsdm_channel,
+ int32_t Offset)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance));
+ assert_param(IS_DFSDM_CHANNEL_OFFSET(Offset));
+
+ /* Check DFSDM channel state */
+ if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Modify channel offset */
+ hdfsdm_channel->Instance->CHCFGR2 &= ~(DFSDM_CHCFGR2_OFFSET);
+ hdfsdm_channel->Instance->CHCFGR2 |= ((uint32_t) Offset << DFSDM_CHCFGR2_OFFSET_Pos);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DFSDM_Exported_Functions_Group3_Channel Channel state function
+ * @brief Channel state function
+ *
+@verbatim
+ ==============================================================================
+ ##### Channel state function #####
+ ==============================================================================
+ [..] This section provides function allowing to:
+ (+) Get channel handle state.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function allows to get the current DFSDM channel handle state.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @retval DFSDM channel state.
+ */
+HAL_DFSDM_Channel_StateTypeDef HAL_DFSDM_ChannelGetState(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+ /* Return DFSDM channel handle state */
+ return hdfsdm_channel->State;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DFSDM_Exported_Functions_Group1_Filter Filter initialization and de-initialization functions
+ * @brief Filter initialization and de-initialization functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Filter initialization and de-initialization functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the DFSDM filter.
+ (+) De-initialize the DFSDM filter.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the DFSDM filter according to the specified parameters
+ * in the DFSDM_FilterInitTypeDef structure and initialize the associated handle.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ const DFSDM_Filter_TypeDef *filter0Instance;
+
+ /* Check DFSDM Channel handle */
+ if(hdfsdm_filter == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+ assert_param(IS_DFSDM_FILTER_REG_TRIGGER(hdfsdm_filter->Init.RegularParam.Trigger));
+ assert_param(IS_FUNCTIONAL_STATE(hdfsdm_filter->Init.RegularParam.FastMode));
+ assert_param(IS_FUNCTIONAL_STATE(hdfsdm_filter->Init.RegularParam.DmaMode));
+ assert_param(IS_DFSDM_FILTER_INJ_TRIGGER(hdfsdm_filter->Init.InjectedParam.Trigger));
+ assert_param(IS_FUNCTIONAL_STATE(hdfsdm_filter->Init.InjectedParam.ScanMode));
+ assert_param(IS_FUNCTIONAL_STATE(hdfsdm_filter->Init.InjectedParam.DmaMode));
+ assert_param(IS_DFSDM_FILTER_SINC_ORDER(hdfsdm_filter->Init.FilterParam.SincOrder));
+ assert_param(IS_DFSDM_FILTER_OVS_RATIO(hdfsdm_filter->Init.FilterParam.Oversampling));
+ assert_param(IS_DFSDM_FILTER_INTEGRATOR_OVS_RATIO(hdfsdm_filter->Init.FilterParam.IntOversampling));
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_FILTER_INSTANCE(hdfsdm_filter->Instance))
+ {
+ filter0Instance = DFSDM1_Filter0;
+ }
+ else
+ {
+ filter0Instance = DFSDM2_Filter0;
+ }
+#else /* DFSDM2_Channel0 */
+ filter0Instance = DFSDM1_Filter0;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check parameters compatibility */
+ if ((hdfsdm_filter->Instance == filter0Instance) &&
+ ((hdfsdm_filter->Init.RegularParam.Trigger == DFSDM_FILTER_SYNC_TRIGGER) ||
+ (hdfsdm_filter->Init.InjectedParam.Trigger == DFSDM_FILTER_SYNC_TRIGGER)))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Initialize DFSDM filter variables with default values */
+ hdfsdm_filter->RegularContMode = DFSDM_CONTINUOUS_CONV_OFF;
+ hdfsdm_filter->InjectedChannelsNbr = 1;
+ hdfsdm_filter->InjConvRemaining = 1;
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_NONE;
+
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ /* Reset callback pointers to the weak predefined callbacks */
+ hdfsdm_filter->AwdCallback = HAL_DFSDM_FilterAwdCallback;
+ hdfsdm_filter->RegConvCpltCallback = HAL_DFSDM_FilterRegConvCpltCallback;
+ hdfsdm_filter->RegConvHalfCpltCallback = HAL_DFSDM_FilterRegConvHalfCpltCallback;
+ hdfsdm_filter->InjConvCpltCallback = HAL_DFSDM_FilterInjConvCpltCallback;
+ hdfsdm_filter->InjConvHalfCpltCallback = HAL_DFSDM_FilterInjConvHalfCpltCallback;
+ hdfsdm_filter->ErrorCallback = HAL_DFSDM_FilterErrorCallback;
+
+ /* Call MSP init function */
+ if(hdfsdm_filter->MspInitCallback == NULL)
+ {
+ hdfsdm_filter->MspInitCallback = HAL_DFSDM_FilterMspInit;
+ }
+ hdfsdm_filter->MspInitCallback(hdfsdm_filter);
+#else
+ /* Call MSP init function */
+ HAL_DFSDM_FilterMspInit(hdfsdm_filter);
+#endif
+
+ /* Set regular parameters */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_RSYNC);
+ if(hdfsdm_filter->Init.RegularParam.FastMode == ENABLE)
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_FAST;
+ }
+ else
+ {
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_FAST);
+ }
+
+ if(hdfsdm_filter->Init.RegularParam.DmaMode == ENABLE)
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RDMAEN;
+ }
+ else
+ {
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_RDMAEN);
+ }
+
+ /* Set injected parameters */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JSYNC | DFSDM_FLTCR1_JEXTEN | DFSDM_FLTCR1_JEXTSEL);
+ if(hdfsdm_filter->Init.InjectedParam.Trigger == DFSDM_FILTER_EXT_TRIGGER)
+ {
+ assert_param(IS_DFSDM_FILTER_EXT_TRIG(hdfsdm_filter->Init.InjectedParam.ExtTrigger));
+ assert_param(IS_DFSDM_FILTER_EXT_TRIG_EDGE(hdfsdm_filter->Init.InjectedParam.ExtTriggerEdge));
+ hdfsdm_filter->Instance->FLTCR1 |= (hdfsdm_filter->Init.InjectedParam.ExtTrigger);
+ }
+
+ if(hdfsdm_filter->Init.InjectedParam.ScanMode == ENABLE)
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSCAN;
+ }
+ else
+ {
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JSCAN);
+ }
+
+ if(hdfsdm_filter->Init.InjectedParam.DmaMode == ENABLE)
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JDMAEN;
+ }
+ else
+ {
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JDMAEN);
+ }
+
+ /* Set filter parameters */
+ hdfsdm_filter->Instance->FLTFCR &= ~(DFSDM_FLTFCR_FORD | DFSDM_FLTFCR_FOSR | DFSDM_FLTFCR_IOSR);
+ hdfsdm_filter->Instance->FLTFCR |= (hdfsdm_filter->Init.FilterParam.SincOrder |
+ ((hdfsdm_filter->Init.FilterParam.Oversampling - 1U) << DFSDM_FLTFCR_FOSR_Pos) |
+ (hdfsdm_filter->Init.FilterParam.IntOversampling - 1U));
+
+ /* Store regular and injected triggers and injected scan mode*/
+ hdfsdm_filter->RegularTrigger = hdfsdm_filter->Init.RegularParam.Trigger;
+ hdfsdm_filter->InjectedTrigger = hdfsdm_filter->Init.InjectedParam.Trigger;
+ hdfsdm_filter->ExtTriggerEdge = hdfsdm_filter->Init.InjectedParam.ExtTriggerEdge;
+ hdfsdm_filter->InjectedScanMode = hdfsdm_filter->Init.InjectedParam.ScanMode;
+
+ /* Enable DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN;
+
+ /* Set DFSDM filter to ready state */
+ hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief De-initializes the DFSDM filter.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Check DFSDM filter handle */
+ if(hdfsdm_filter == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Disable the DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN);
+
+ /* Call MSP deinit function */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ if(hdfsdm_filter->MspDeInitCallback == NULL)
+ {
+ hdfsdm_filter->MspDeInitCallback = HAL_DFSDM_FilterMspDeInit;
+ }
+ hdfsdm_filter->MspDeInitCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterMspDeInit(hdfsdm_filter);
+#endif
+
+ /* Set DFSDM filter in reset state */
+ hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_RESET;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the DFSDM filter MSP.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_filter);
+
+ /* NOTE : This function should not be modified, when the function is needed,
+ the HAL_DFSDM_FilterMspInit could be implemented in the user file.
+ */
+}
+
+/**
+ * @brief De-initializes the DFSDM filter MSP.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_filter);
+
+ /* NOTE : This function should not be modified, when the function is needed,
+ the HAL_DFSDM_FilterMspDeInit could be implemented in the user file.
+ */
+}
+
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a user DFSDM filter callback
+ * to be used instead of the weak predefined callback.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param CallbackID ID of the callback to be registered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DFSDM_FILTER_REGCONV_COMPLETE_CB_ID regular conversion complete callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_REGCONV_HALFCOMPLETE_CB_ID half regular conversion complete callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_INJCONV_COMPLETE_CB_ID injected conversion complete callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_INJCONV_HALFCOMPLETE_CB_ID half injected conversion complete callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_ERROR_CB_ID error callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @param pCallback pointer to the callback function.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_Filter_RegisterCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ HAL_DFSDM_Filter_CallbackIDTypeDef CallbackID,
+ pDFSDM_Filter_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ if(HAL_DFSDM_FILTER_STATE_READY == hdfsdm_filter->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DFSDM_FILTER_REGCONV_COMPLETE_CB_ID :
+ hdfsdm_filter->RegConvCpltCallback = pCallback;
+ break;
+ case HAL_DFSDM_FILTER_REGCONV_HALFCOMPLETE_CB_ID :
+ hdfsdm_filter->RegConvHalfCpltCallback = pCallback;
+ break;
+ case HAL_DFSDM_FILTER_INJCONV_COMPLETE_CB_ID :
+ hdfsdm_filter->InjConvCpltCallback = pCallback;
+ break;
+ case HAL_DFSDM_FILTER_INJCONV_HALFCOMPLETE_CB_ID :
+ hdfsdm_filter->InjConvHalfCpltCallback = pCallback;
+ break;
+ case HAL_DFSDM_FILTER_ERROR_CB_ID :
+ hdfsdm_filter->ErrorCallback = pCallback;
+ break;
+ case HAL_DFSDM_FILTER_MSPINIT_CB_ID :
+ hdfsdm_filter->MspInitCallback = pCallback;
+ break;
+ case HAL_DFSDM_FILTER_MSPDEINIT_CB_ID :
+ hdfsdm_filter->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_DFSDM_FILTER_STATE_RESET == hdfsdm_filter->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DFSDM_FILTER_MSPINIT_CB_ID :
+ hdfsdm_filter->MspInitCallback = pCallback;
+ break;
+ case HAL_DFSDM_FILTER_MSPDEINIT_CB_ID :
+ hdfsdm_filter->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Unregister a user DFSDM filter callback.
+ * DFSDM filter callback is redirected to the weak predefined callback.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param CallbackID ID of the callback to be unregistered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DFSDM_FILTER_REGCONV_COMPLETE_CB_ID regular conversion complete callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_REGCONV_HALFCOMPLETE_CB_ID half regular conversion complete callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_INJCONV_COMPLETE_CB_ID injected conversion complete callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_INJCONV_HALFCOMPLETE_CB_ID half injected conversion complete callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_ERROR_CB_ID error callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_DFSDM_FILTER_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_Filter_UnRegisterCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ HAL_DFSDM_Filter_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(HAL_DFSDM_FILTER_STATE_READY == hdfsdm_filter->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DFSDM_FILTER_REGCONV_COMPLETE_CB_ID :
+ hdfsdm_filter->RegConvCpltCallback = HAL_DFSDM_FilterRegConvCpltCallback;
+ break;
+ case HAL_DFSDM_FILTER_REGCONV_HALFCOMPLETE_CB_ID :
+ hdfsdm_filter->RegConvHalfCpltCallback = HAL_DFSDM_FilterRegConvHalfCpltCallback;
+ break;
+ case HAL_DFSDM_FILTER_INJCONV_COMPLETE_CB_ID :
+ hdfsdm_filter->InjConvCpltCallback = HAL_DFSDM_FilterInjConvCpltCallback;
+ break;
+ case HAL_DFSDM_FILTER_INJCONV_HALFCOMPLETE_CB_ID :
+ hdfsdm_filter->InjConvHalfCpltCallback = HAL_DFSDM_FilterInjConvHalfCpltCallback;
+ break;
+ case HAL_DFSDM_FILTER_ERROR_CB_ID :
+ hdfsdm_filter->ErrorCallback = HAL_DFSDM_FilterErrorCallback;
+ break;
+ case HAL_DFSDM_FILTER_MSPINIT_CB_ID :
+ hdfsdm_filter->MspInitCallback = HAL_DFSDM_FilterMspInit;
+ break;
+ case HAL_DFSDM_FILTER_MSPDEINIT_CB_ID :
+ hdfsdm_filter->MspDeInitCallback = HAL_DFSDM_FilterMspDeInit;
+ break;
+ default :
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_DFSDM_FILTER_STATE_RESET == hdfsdm_filter->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DFSDM_FILTER_MSPINIT_CB_ID :
+ hdfsdm_filter->MspInitCallback = HAL_DFSDM_FilterMspInit;
+ break;
+ case HAL_DFSDM_FILTER_MSPDEINIT_CB_ID :
+ hdfsdm_filter->MspDeInitCallback = HAL_DFSDM_FilterMspDeInit;
+ break;
+ default :
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ return status;
+}
+
+/**
+ * @brief Register a user DFSDM filter analog watchdog callback
+ * to be used instead of the weak predefined callback.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param pCallback pointer to the DFSDM filter analog watchdog callback function.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_Filter_RegisterAwdCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ pDFSDM_Filter_AwdCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ if(HAL_DFSDM_FILTER_STATE_READY == hdfsdm_filter->State)
+ {
+ hdfsdm_filter->AwdCallback = pCallback;
+ }
+ else
+ {
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Unregister a user DFSDM filter analog watchdog callback.
+ * DFSDM filter AWD callback is redirected to the weak predefined callback.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFSDM_Filter_UnRegisterAwdCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(HAL_DFSDM_FILTER_STATE_READY == hdfsdm_filter->State)
+ {
+ hdfsdm_filter->AwdCallback = HAL_DFSDM_FilterAwdCallback;
+ }
+ else
+ {
+ /* update the error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ return status;
+}
+#endif /* USE_HAL_DFSDM_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup DFSDM_Exported_Functions_Group2_Filter Filter control functions
+ * @brief Filter control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Filter control functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Select channel and enable/disable continuous mode for regular conversion.
+ (+) Select channels for injected conversion.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function allows to select channel and to enable/disable
+ * continuous mode for regular conversion.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Channel Channel for regular conversion.
+ * This parameter can be a value of @ref DFSDM_Channel_Selection.
+ * @param ContinuousMode Enable/disable continuous mode for regular conversion.
+ * This parameter can be a value of @ref DFSDM_ContinuousMode.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterConfigRegChannel(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t Channel,
+ uint32_t ContinuousMode)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+ assert_param(IS_DFSDM_REGULAR_CHANNEL(Channel));
+ assert_param(IS_DFSDM_CONTINUOUS_MODE(ContinuousMode));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_RESET) &&
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_ERROR))
+ {
+ /* Configure channel and continuous mode for regular conversion */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_RCH | DFSDM_FLTCR1_RCONT);
+ if(ContinuousMode == DFSDM_CONTINUOUS_CONV_ON)
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= (uint32_t) (((Channel & DFSDM_MSB_MASK) << DFSDM_FLTCR1_MSB_RCH_OFFSET) |
+ DFSDM_FLTCR1_RCONT);
+ }
+ else
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= (uint32_t) ((Channel & DFSDM_MSB_MASK) << DFSDM_FLTCR1_MSB_RCH_OFFSET);
+ }
+ /* Store continuous mode information */
+ hdfsdm_filter->RegularContMode = ContinuousMode;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to select channels for injected conversion.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Channel Channels for injected conversion.
+ * This parameter can be a values combination of @ref DFSDM_Channel_Selection.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterConfigInjChannel(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+ assert_param(IS_DFSDM_INJECTED_CHANNEL(Channel));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_RESET) &&
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_ERROR))
+ {
+ /* Configure channel for injected conversion */
+ hdfsdm_filter->Instance->FLTJCHGR = (uint32_t) (Channel & DFSDM_LSB_MASK);
+ /* Store number of injected channels */
+ hdfsdm_filter->InjectedChannelsNbr = DFSDM_GetInjChannelsNbr(Channel);
+ /* Update number of injected channels remaining */
+ hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \
+ hdfsdm_filter->InjectedChannelsNbr : 1U;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DFSDM_Exported_Functions_Group3_Filter Filter operation functions
+ * @brief Filter operation functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Filter operation functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start conversion of regular/injected channel.
+ (+) Poll for the end of regular/injected conversion.
+ (+) Stop conversion of regular/injected channel.
+ (+) Start conversion of regular/injected channel and enable interrupt.
+ (+) Call the callback functions at the end of regular/injected conversions.
+ (+) Stop conversion of regular/injected channel and disable interrupt.
+ (+) Start conversion of regular/injected channel and enable DMA transfer.
+ (+) Stop conversion of regular/injected channel and disable DMA transfer.
+ (+) Start analog watchdog and enable interrupt.
+ (+) Call the callback function when analog watchdog occurs.
+ (+) Stop analog watchdog and disable interrupt.
+ (+) Start extreme detector.
+ (+) Stop extreme detector.
+ (+) Get result of regular channel conversion.
+ (+) Get result of injected channel conversion.
+ (+) Get extreme detector maximum and minimum values.
+ (+) Get conversion time.
+ (+) Handle DFSDM interrupt request.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function allows to start regular conversion in polling mode.
+ * @note This function should be called only when DFSDM filter instance is
+ * in idle state or if injected conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterRegularStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ))
+ {
+ /* Start regular conversion */
+ DFSDM_RegConvStart(hdfsdm_filter);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to poll for the end of regular conversion.
+ * @note This function should be called only if regular conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Timeout Timeout value in milliseconds.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterPollForRegConversion(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG) && \
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ))
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait end of regular conversion */
+ while((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_REOCF) != DFSDM_FLTISR_REOCF)
+ {
+ /* Check the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Return timeout status */
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ /* Check if overrun occurs */
+ if((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_ROVRF) == DFSDM_FLTISR_ROVRF)
+ {
+ /* Update error code and call error callback */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_REGULAR_OVERRUN;
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->ErrorCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterErrorCallback(hdfsdm_filter);
+#endif
+
+ /* Clear regular overrun flag */
+ hdfsdm_filter->Instance->FLTICR = DFSDM_FLTICR_CLRROVRF;
+ }
+ /* Update DFSDM filter state only if not continuous conversion and SW trigger */
+ if((hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \
+ (hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER))
+ {
+ hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG) ? \
+ HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_INJ;
+ }
+ /* Return function status */
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief This function allows to stop regular conversion in polling mode.
+ * @note This function should be called only if regular conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterRegularStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG) && \
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop regular conversion */
+ DFSDM_RegConvStop(hdfsdm_filter);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start regular conversion in interrupt mode.
+ * @note This function should be called only when DFSDM filter instance is
+ * in idle state or if injected conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterRegularStart_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ))
+ {
+ /* Enable interrupts for regular conversions */
+ hdfsdm_filter->Instance->FLTCR2 |= (DFSDM_FLTCR2_REOCIE | DFSDM_FLTCR2_ROVRIE);
+
+ /* Start regular conversion */
+ DFSDM_RegConvStart(hdfsdm_filter);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to stop regular conversion in interrupt mode.
+ * @note This function should be called only if regular conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterRegularStop_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG) && \
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Disable interrupts for regular conversions */
+ hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_REOCIE | DFSDM_FLTCR2_ROVRIE);
+
+ /* Stop regular conversion */
+ DFSDM_RegConvStop(hdfsdm_filter);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start regular conversion in DMA mode.
+ * @note This function should be called only when DFSDM filter instance is
+ * in idle state or if injected conversion is ongoing.
+ * Please note that data on buffer will contain signed regular conversion
+ * value on 24 most significant bits and corresponding channel on 3 least
+ * significant bits.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param pData The destination buffer address.
+ * @param Length The length of data to be transferred from DFSDM filter to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterRegularStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ int32_t *pData,
+ uint32_t Length)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check destination address and length */
+ if((pData == NULL) || (Length == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ /* Check that DMA is enabled for regular conversion */
+ else if((hdfsdm_filter->Instance->FLTCR1 & DFSDM_FLTCR1_RDMAEN) != DFSDM_FLTCR1_RDMAEN)
+ {
+ status = HAL_ERROR;
+ }
+ /* Check parameters compatibility */
+ else if((hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER) && \
+ (hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \
+ (hdfsdm_filter->hdmaReg->Init.Mode == DMA_NORMAL) && \
+ (Length != 1U))
+ {
+ status = HAL_ERROR;
+ }
+ else if((hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER) && \
+ (hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \
+ (hdfsdm_filter->hdmaReg->Init.Mode == DMA_CIRCULAR))
+ {
+ status = HAL_ERROR;
+ }
+ /* Check DFSDM filter state */
+ else if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ))
+ {
+ /* Set callbacks on DMA handler */
+ hdfsdm_filter->hdmaReg->XferCpltCallback = DFSDM_DMARegularConvCplt;
+ hdfsdm_filter->hdmaReg->XferErrorCallback = DFSDM_DMAError;
+ hdfsdm_filter->hdmaReg->XferHalfCpltCallback = (hdfsdm_filter->hdmaReg->Init.Mode == DMA_CIRCULAR) ?\
+ DFSDM_DMARegularHalfConvCplt : NULL;
+
+ /* Start DMA in interrupt mode */
+ if(HAL_DMA_Start_IT(hdfsdm_filter->hdmaReg, (uint32_t)&hdfsdm_filter->Instance->FLTRDATAR, \
+ (uint32_t) pData, Length) != HAL_OK)
+ {
+ /* Set DFSDM filter in error state */
+ hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR;
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Start regular conversion */
+ DFSDM_RegConvStart(hdfsdm_filter);
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start regular conversion in DMA mode and to get
+ * only the 16 most significant bits of conversion.
+ * @note This function should be called only when DFSDM filter instance is
+ * in idle state or if injected conversion is ongoing.
+ * Please note that data on buffer will contain signed 16 most significant
+ * bits of regular conversion.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param pData The destination buffer address.
+ * @param Length The length of data to be transferred from DFSDM filter to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterRegularMsbStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ int16_t *pData,
+ uint32_t Length)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check destination address and length */
+ if((pData == NULL) || (Length == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ /* Check that DMA is enabled for regular conversion */
+ else if((hdfsdm_filter->Instance->FLTCR1 & DFSDM_FLTCR1_RDMAEN) != DFSDM_FLTCR1_RDMAEN)
+ {
+ status = HAL_ERROR;
+ }
+ /* Check parameters compatibility */
+ else if((hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER) && \
+ (hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \
+ (hdfsdm_filter->hdmaReg->Init.Mode == DMA_NORMAL) && \
+ (Length != 1U))
+ {
+ status = HAL_ERROR;
+ }
+ else if((hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER) && \
+ (hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \
+ (hdfsdm_filter->hdmaReg->Init.Mode == DMA_CIRCULAR))
+ {
+ status = HAL_ERROR;
+ }
+ /* Check DFSDM filter state */
+ else if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ))
+ {
+ /* Set callbacks on DMA handler */
+ hdfsdm_filter->hdmaReg->XferCpltCallback = DFSDM_DMARegularConvCplt;
+ hdfsdm_filter->hdmaReg->XferErrorCallback = DFSDM_DMAError;
+ hdfsdm_filter->hdmaReg->XferHalfCpltCallback = (hdfsdm_filter->hdmaReg->Init.Mode == DMA_CIRCULAR) ?\
+ DFSDM_DMARegularHalfConvCplt : NULL;
+
+ /* Start DMA in interrupt mode */
+ if(HAL_DMA_Start_IT(hdfsdm_filter->hdmaReg, (uint32_t)(&hdfsdm_filter->Instance->FLTRDATAR) + 2U, \
+ (uint32_t) pData, Length) != HAL_OK)
+ {
+ /* Set DFSDM filter in error state */
+ hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR;
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Start regular conversion */
+ DFSDM_RegConvStart(hdfsdm_filter);
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to stop regular conversion in DMA mode.
+ * @note This function should be called only if regular conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterRegularStop_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG) && \
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop current DMA transfer */
+ if(HAL_DMA_Abort(hdfsdm_filter->hdmaReg) != HAL_OK)
+ {
+ /* Set DFSDM filter in error state */
+ hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR;
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop regular conversion */
+ DFSDM_RegConvStop(hdfsdm_filter);
+ }
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to get regular conversion value.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Channel Corresponding channel of regular conversion.
+ * @retval Regular conversion value
+ */
+int32_t HAL_DFSDM_FilterGetRegularValue(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t *Channel)
+{
+ uint32_t reg;
+ int32_t value;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+ assert_param(Channel != (void *)0);
+
+ /* Get value of data register for regular channel */
+ reg = hdfsdm_filter->Instance->FLTRDATAR;
+
+ /* Extract channel and regular conversion value */
+ *Channel = (reg & DFSDM_FLTRDATAR_RDATACH);
+ /* Regular conversion value is a signed value located on 24 MSB of register */
+ /* So after applying a mask on these bits we have to perform a division by 256 (2 raised to the power of 8) */
+ reg &= DFSDM_FLTRDATAR_RDATA;
+ value = ((int32_t)reg) / 256;
+
+ /* return regular conversion value */
+ return value;
+}
+
+/**
+ * @brief This function allows to start injected conversion in polling mode.
+ * @note This function should be called only when DFSDM filter instance is
+ * in idle state or if regular conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG))
+ {
+ /* Start injected conversion */
+ DFSDM_InjConvStart(hdfsdm_filter);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to poll for the end of injected conversion.
+ * @note This function should be called only if injected conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Timeout Timeout value in milliseconds.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterPollForInjConversion(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_INJ) && \
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ))
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait end of injected conversions */
+ while((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_JEOCF) != DFSDM_FLTISR_JEOCF)
+ {
+ /* Check the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Return timeout status */
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ /* Check if overrun occurs */
+ if((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_JOVRF) == DFSDM_FLTISR_JOVRF)
+ {
+ /* Update error code and call error callback */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INJECTED_OVERRUN;
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->ErrorCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterErrorCallback(hdfsdm_filter);
+#endif
+
+ /* Clear injected overrun flag */
+ hdfsdm_filter->Instance->FLTICR = DFSDM_FLTICR_CLRJOVRF;
+ }
+
+ /* Update remaining injected conversions */
+ hdfsdm_filter->InjConvRemaining--;
+ if(hdfsdm_filter->InjConvRemaining == 0U)
+ {
+ /* Update DFSDM filter state only if trigger is software */
+ if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER)
+ {
+ hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ) ? \
+ HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_REG;
+ }
+
+ /* end of injected sequence, reset the value */
+ hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \
+ hdfsdm_filter->InjectedChannelsNbr : 1U;
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief This function allows to stop injected conversion in polling mode.
+ * @note This function should be called only if injected conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_INJ) && \
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop injected conversion */
+ DFSDM_InjConvStop(hdfsdm_filter);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start injected conversion in interrupt mode.
+ * @note This function should be called only when DFSDM filter instance is
+ * in idle state or if regular conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStart_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG))
+ {
+ /* Enable interrupts for injected conversions */
+ hdfsdm_filter->Instance->FLTCR2 |= (DFSDM_FLTCR2_JEOCIE | DFSDM_FLTCR2_JOVRIE);
+
+ /* Start injected conversion */
+ DFSDM_InjConvStart(hdfsdm_filter);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to stop injected conversion in interrupt mode.
+ * @note This function should be called only if injected conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStop_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_INJ) && \
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Disable interrupts for injected conversions */
+ hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_JEOCIE | DFSDM_FLTCR2_JOVRIE);
+
+ /* Stop injected conversion */
+ DFSDM_InjConvStop(hdfsdm_filter);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start injected conversion in DMA mode.
+ * @note This function should be called only when DFSDM filter instance is
+ * in idle state or if regular conversion is ongoing.
+ * Please note that data on buffer will contain signed injected conversion
+ * value on 24 most significant bits and corresponding channel on 3 least
+ * significant bits.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param pData The destination buffer address.
+ * @param Length The length of data to be transferred from DFSDM filter to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ int32_t *pData,
+ uint32_t Length)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check destination address and length */
+ if((pData == NULL) || (Length == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ /* Check that DMA is enabled for injected conversion */
+ else if((hdfsdm_filter->Instance->FLTCR1 & DFSDM_FLTCR1_JDMAEN) != DFSDM_FLTCR1_JDMAEN)
+ {
+ status = HAL_ERROR;
+ }
+ /* Check parameters compatibility */
+ else if((hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) && \
+ (hdfsdm_filter->hdmaInj->Init.Mode == DMA_NORMAL) && \
+ (Length > hdfsdm_filter->InjConvRemaining))
+ {
+ status = HAL_ERROR;
+ }
+ else if((hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) && \
+ (hdfsdm_filter->hdmaInj->Init.Mode == DMA_CIRCULAR))
+ {
+ status = HAL_ERROR;
+ }
+ /* Check DFSDM filter state */
+ else if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG))
+ {
+ /* Set callbacks on DMA handler */
+ hdfsdm_filter->hdmaInj->XferCpltCallback = DFSDM_DMAInjectedConvCplt;
+ hdfsdm_filter->hdmaInj->XferErrorCallback = DFSDM_DMAError;
+ hdfsdm_filter->hdmaInj->XferHalfCpltCallback = (hdfsdm_filter->hdmaInj->Init.Mode == DMA_CIRCULAR) ?\
+ DFSDM_DMAInjectedHalfConvCplt : NULL;
+
+ /* Start DMA in interrupt mode */
+ if(HAL_DMA_Start_IT(hdfsdm_filter->hdmaInj, (uint32_t)&hdfsdm_filter->Instance->FLTJDATAR, \
+ (uint32_t) pData, Length) != HAL_OK)
+ {
+ /* Set DFSDM filter in error state */
+ hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR;
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Start injected conversion */
+ DFSDM_InjConvStart(hdfsdm_filter);
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start injected conversion in DMA mode and to get
+ * only the 16 most significant bits of conversion.
+ * @note This function should be called only when DFSDM filter instance is
+ * in idle state or if regular conversion is ongoing.
+ * Please note that data on buffer will contain signed 16 most significant
+ * bits of injected conversion.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param pData The destination buffer address.
+ * @param Length The length of data to be transferred from DFSDM filter to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterInjectedMsbStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ int16_t *pData,
+ uint32_t Length)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check destination address and length */
+ if((pData == NULL) || (Length == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ /* Check that DMA is enabled for injected conversion */
+ else if((hdfsdm_filter->Instance->FLTCR1 & DFSDM_FLTCR1_JDMAEN) != DFSDM_FLTCR1_JDMAEN)
+ {
+ status = HAL_ERROR;
+ }
+ /* Check parameters compatibility */
+ else if((hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) && \
+ (hdfsdm_filter->hdmaInj->Init.Mode == DMA_NORMAL) && \
+ (Length > hdfsdm_filter->InjConvRemaining))
+ {
+ status = HAL_ERROR;
+ }
+ else if((hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) && \
+ (hdfsdm_filter->hdmaInj->Init.Mode == DMA_CIRCULAR))
+ {
+ status = HAL_ERROR;
+ }
+ /* Check DFSDM filter state */
+ else if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG))
+ {
+ /* Set callbacks on DMA handler */
+ hdfsdm_filter->hdmaInj->XferCpltCallback = DFSDM_DMAInjectedConvCplt;
+ hdfsdm_filter->hdmaInj->XferErrorCallback = DFSDM_DMAError;
+ hdfsdm_filter->hdmaInj->XferHalfCpltCallback = (hdfsdm_filter->hdmaInj->Init.Mode == DMA_CIRCULAR) ?\
+ DFSDM_DMAInjectedHalfConvCplt : NULL;
+
+ /* Start DMA in interrupt mode */
+ if(HAL_DMA_Start_IT(hdfsdm_filter->hdmaInj, (uint32_t)(&hdfsdm_filter->Instance->FLTJDATAR) + 2U, \
+ (uint32_t) pData, Length) != HAL_OK)
+ {
+ /* Set DFSDM filter in error state */
+ hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR;
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Start injected conversion */
+ DFSDM_InjConvStart(hdfsdm_filter);
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to stop injected conversion in DMA mode.
+ * @note This function should be called only if injected conversion is ongoing.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStop_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_INJ) && \
+ (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop current DMA transfer */
+ if(HAL_DMA_Abort(hdfsdm_filter->hdmaInj) != HAL_OK)
+ {
+ /* Set DFSDM filter in error state */
+ hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR;
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Stop regular conversion */
+ DFSDM_InjConvStop(hdfsdm_filter);
+ }
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to get injected conversion value.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Channel Corresponding channel of injected conversion.
+ * @retval Injected conversion value
+ */
+int32_t HAL_DFSDM_FilterGetInjectedValue(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t *Channel)
+{
+ uint32_t reg;
+ int32_t value;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+ assert_param(Channel != (void *)0);
+
+ /* Get value of data register for injected channel */
+ reg = hdfsdm_filter->Instance->FLTJDATAR;
+
+ /* Extract channel and injected conversion value */
+ *Channel = (reg & DFSDM_FLTJDATAR_JDATACH);
+ /* Injected conversion value is a signed value located on 24 MSB of register */
+ /* So after applying a mask on these bits we have to perform a division by 256 (2 raised to the power of 8) */
+ reg &= DFSDM_FLTJDATAR_JDATA;
+ value = ((int32_t)reg) / 256;
+
+ /* return regular conversion value */
+ return value;
+}
+
+/**
+ * @brief This function allows to start filter analog watchdog in interrupt mode.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param awdParam DFSDM filter analog watchdog parameters.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterAwdStart_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ DFSDM_Filter_AwdParamTypeDef *awdParam)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+ assert_param(IS_DFSDM_FILTER_AWD_DATA_SOURCE(awdParam->DataSource));
+ assert_param(IS_DFSDM_INJECTED_CHANNEL(awdParam->Channel));
+ assert_param(IS_DFSDM_FILTER_AWD_THRESHOLD(awdParam->HighThreshold));
+ assert_param(IS_DFSDM_FILTER_AWD_THRESHOLD(awdParam->LowThreshold));
+ assert_param(IS_DFSDM_BREAK_SIGNALS(awdParam->HighBreakSignal));
+ assert_param(IS_DFSDM_BREAK_SIGNALS(awdParam->LowBreakSignal));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_RESET) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_ERROR))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Set analog watchdog data source */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_AWFSEL);
+ hdfsdm_filter->Instance->FLTCR1 |= awdParam->DataSource;
+
+ /* Set thresholds and break signals */
+ hdfsdm_filter->Instance->FLTAWHTR &= ~(DFSDM_FLTAWHTR_AWHT | DFSDM_FLTAWHTR_BKAWH);
+ hdfsdm_filter->Instance->FLTAWHTR |= (((uint32_t) awdParam->HighThreshold << DFSDM_FLTAWHTR_AWHT_Pos) | \
+ awdParam->HighBreakSignal);
+ hdfsdm_filter->Instance->FLTAWLTR &= ~(DFSDM_FLTAWLTR_AWLT | DFSDM_FLTAWLTR_BKAWL);
+ hdfsdm_filter->Instance->FLTAWLTR |= (((uint32_t) awdParam->LowThreshold << DFSDM_FLTAWLTR_AWLT_Pos) | \
+ awdParam->LowBreakSignal);
+
+ /* Set channels and interrupt for analog watchdog */
+ hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_AWDCH);
+ hdfsdm_filter->Instance->FLTCR2 |= (((awdParam->Channel & DFSDM_LSB_MASK) << DFSDM_FLTCR2_AWDCH_Pos) | \
+ DFSDM_FLTCR2_AWDIE);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to stop filter analog watchdog in interrupt mode.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterAwdStop_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_RESET) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_ERROR))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Reset channels for analog watchdog and deactivate interrupt */
+ hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_AWDCH | DFSDM_FLTCR2_AWDIE);
+
+ /* Clear all analog watchdog flags */
+ hdfsdm_filter->Instance->FLTAWCFR = (DFSDM_FLTAWCFR_CLRAWHTF | DFSDM_FLTAWCFR_CLRAWLTF);
+
+ /* Reset thresholds and break signals */
+ hdfsdm_filter->Instance->FLTAWHTR &= ~(DFSDM_FLTAWHTR_AWHT | DFSDM_FLTAWHTR_BKAWH);
+ hdfsdm_filter->Instance->FLTAWLTR &= ~(DFSDM_FLTAWLTR_AWLT | DFSDM_FLTAWLTR_BKAWL);
+
+ /* Reset analog watchdog data source */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_AWFSEL);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to start extreme detector feature.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Channel Channels where extreme detector is enabled.
+ * This parameter can be a values combination of @ref DFSDM_Channel_Selection.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterExdStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+ assert_param(IS_DFSDM_INJECTED_CHANNEL(Channel));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_RESET) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_ERROR))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Set channels for extreme detector */
+ hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_EXCH);
+ hdfsdm_filter->Instance->FLTCR2 |= ((Channel & DFSDM_LSB_MASK) << DFSDM_FLTCR2_EXCH_Pos);
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to stop extreme detector feature.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DFSDM_FilterExdStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ __IO uint32_t reg1;
+ __IO uint32_t reg2;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Check DFSDM filter state */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_RESET) || \
+ (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_ERROR))
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Reset channels for extreme detector */
+ hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_EXCH);
+
+ /* Clear extreme detector values */
+ reg1 = hdfsdm_filter->Instance->FLTEXMAX;
+ reg2 = hdfsdm_filter->Instance->FLTEXMIN;
+ UNUSED(reg1); /* To avoid GCC warning */
+ UNUSED(reg2); /* To avoid GCC warning */
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to get extreme detector maximum value.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Channel Corresponding channel.
+ * @retval Extreme detector maximum value
+ * This value is between Min_Data = -8388608 and Max_Data = 8388607.
+ */
+int32_t HAL_DFSDM_FilterGetExdMaxValue(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t *Channel)
+{
+ uint32_t reg;
+ int32_t value;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+ assert_param(Channel != (void *)0);
+
+ /* Get value of extreme detector maximum register */
+ reg = hdfsdm_filter->Instance->FLTEXMAX;
+
+ /* Extract channel and extreme detector maximum value */
+ *Channel = (reg & DFSDM_FLTEXMAX_EXMAXCH);
+ /* Extreme detector maximum value is a signed value located on 24 MSB of register */
+ /* So after applying a mask on these bits we have to perform a division by 256 (2 raised to the power of 8) */
+ reg &= DFSDM_FLTEXMAX_EXMAX;
+ value = ((int32_t)reg) / 256;
+
+ /* return extreme detector maximum value */
+ return value;
+}
+
+/**
+ * @brief This function allows to get extreme detector minimum value.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Channel Corresponding channel.
+ * @retval Extreme detector minimum value
+ * This value is between Min_Data = -8388608 and Max_Data = 8388607.
+ */
+int32_t HAL_DFSDM_FilterGetExdMinValue(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t *Channel)
+{
+ uint32_t reg;
+ int32_t value;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+ assert_param(Channel != (void *)0);
+
+ /* Get value of extreme detector minimum register */
+ reg = hdfsdm_filter->Instance->FLTEXMIN;
+
+ /* Extract channel and extreme detector minimum value */
+ *Channel = (reg & DFSDM_FLTEXMIN_EXMINCH);
+ /* Extreme detector minimum value is a signed value located on 24 MSB of register */
+ /* So after applying a mask on these bits we have to perform a division by 256 (2 raised to the power of 8) */
+ reg &= DFSDM_FLTEXMIN_EXMIN;
+ value = ((int32_t)reg) / 256;
+
+ /* return extreme detector minimum value */
+ return value;
+}
+
+/**
+ * @brief This function allows to get conversion time value.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval Conversion time value
+ * @note To get time in second, this value has to be divided by DFSDM clock frequency.
+ */
+uint32_t HAL_DFSDM_FilterGetConvTimeValue(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ uint32_t reg;
+ uint32_t value;
+
+ /* Check parameters */
+ assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance));
+
+ /* Get value of conversion timer register */
+ reg = hdfsdm_filter->Instance->FLTCNVTIMR;
+
+ /* Extract conversion time value */
+ value = ((reg & DFSDM_FLTCNVTIMR_CNVCNT) >> DFSDM_FLTCNVTIMR_CNVCNT_Pos);
+
+ /* return extreme detector minimum value */
+ return value;
+}
+
+/**
+ * @brief This function handles the DFSDM interrupts.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+void HAL_DFSDM_IRQHandler(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ DFSDM_Channel_HandleTypeDef **channelHandleTable;
+ const DFSDM_Filter_TypeDef *filter0Instance;
+ uint32_t channelNumber;
+
+ /* Get FTLISR and FLTCR2 register values */
+ const uint32_t temp_fltisr = hdfsdm_filter->Instance->FLTISR;
+ const uint32_t temp_fltcr2 = hdfsdm_filter->Instance->FLTCR2;
+
+#if defined(DFSDM2_Channel0)
+ if (IS_DFSDM1_FILTER_INSTANCE(hdfsdm_filter->Instance))
+ {
+ channelHandleTable = a_dfsdm1ChannelHandle;
+ filter0Instance = DFSDM1_Filter0;
+ channelNumber = DFSDM1_CHANNEL_NUMBER;
+ }
+ else
+ {
+ channelHandleTable = a_dfsdm2ChannelHandle;
+ filter0Instance = DFSDM2_Filter0;
+ channelNumber = DFSDM2_CHANNEL_NUMBER;
+ }
+#else /* DFSDM2_Channel0 */
+ channelHandleTable = a_dfsdm1ChannelHandle;
+ filter0Instance = DFSDM1_Filter0;
+ channelNumber = DFSDM1_CHANNEL_NUMBER;
+#endif /* DFSDM2_Channel0 */
+
+ /* Check if overrun occurs during regular conversion */
+ if(((temp_fltisr & DFSDM_FLTISR_ROVRF) != 0U) && \
+ ((temp_fltcr2 & DFSDM_FLTCR2_ROVRIE) != 0U))
+ {
+ /* Clear regular overrun flag */
+ hdfsdm_filter->Instance->FLTICR = DFSDM_FLTICR_CLRROVRF;
+
+ /* Update error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_REGULAR_OVERRUN;
+
+ /* Call error callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->ErrorCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterErrorCallback(hdfsdm_filter);
+#endif
+ }
+ /* Check if overrun occurs during injected conversion */
+ else if(((temp_fltisr & DFSDM_FLTISR_JOVRF) != 0U) && \
+ ((temp_fltcr2 & DFSDM_FLTCR2_JOVRIE) != 0U))
+ {
+ /* Clear injected overrun flag */
+ hdfsdm_filter->Instance->FLTICR = DFSDM_FLTICR_CLRJOVRF;
+
+ /* Update error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INJECTED_OVERRUN;
+
+ /* Call error callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->ErrorCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterErrorCallback(hdfsdm_filter);
+#endif
+ }
+ /* Check if end of regular conversion */
+ else if(((temp_fltisr & DFSDM_FLTISR_REOCF) != 0U) && \
+ ((temp_fltcr2 & DFSDM_FLTCR2_REOCIE) != 0U))
+ {
+ /* Call regular conversion complete callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->RegConvCpltCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterRegConvCpltCallback(hdfsdm_filter);
+#endif
+
+ /* End of conversion if mode is not continuous and software trigger */
+ if((hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \
+ (hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER))
+ {
+ /* Disable interrupts for regular conversions */
+ hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_REOCIE);
+
+ /* Update DFSDM filter state */
+ hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG) ? \
+ HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_INJ;
+ }
+ }
+ /* Check if end of injected conversion */
+ else if(((temp_fltisr & DFSDM_FLTISR_JEOCF) != 0U) && \
+ ((temp_fltcr2 & DFSDM_FLTCR2_JEOCIE) != 0U))
+ {
+ /* Call injected conversion complete callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->InjConvCpltCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterInjConvCpltCallback(hdfsdm_filter);
+#endif
+
+ /* Update remaining injected conversions */
+ hdfsdm_filter->InjConvRemaining--;
+ if(hdfsdm_filter->InjConvRemaining == 0U)
+ {
+ /* End of conversion if trigger is software */
+ if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER)
+ {
+ /* Disable interrupts for injected conversions */
+ hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_JEOCIE);
+
+ /* Update DFSDM filter state */
+ hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ) ? \
+ HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_REG;
+ }
+ /* end of injected sequence, reset the value */
+ hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \
+ hdfsdm_filter->InjectedChannelsNbr : 1U;
+ }
+ }
+ /* Check if analog watchdog occurs */
+ else if(((temp_fltisr & DFSDM_FLTISR_AWDF) != 0U) && \
+ ((temp_fltcr2 & DFSDM_FLTCR2_AWDIE) != 0U))
+ {
+ uint32_t reg;
+ uint32_t threshold;
+ uint32_t channel = 0;
+
+ /* Get channel and threshold */
+ reg = hdfsdm_filter->Instance->FLTAWSR;
+ threshold = ((reg & DFSDM_FLTAWSR_AWLTF) != 0U) ? DFSDM_AWD_LOW_THRESHOLD : DFSDM_AWD_HIGH_THRESHOLD;
+ if(threshold == DFSDM_AWD_HIGH_THRESHOLD)
+ {
+ reg = reg >> DFSDM_FLTAWSR_AWHTF_Pos;
+ }
+ while (((reg & 1U) == 0U) && (channel < (channelNumber - 1U)))
+ {
+ channel++;
+ reg = reg >> 1;
+ }
+ /* Clear analog watchdog flag */
+ hdfsdm_filter->Instance->FLTAWCFR = (threshold == DFSDM_AWD_HIGH_THRESHOLD) ? \
+ (1UL << (DFSDM_FLTAWSR_AWHTF_Pos + channel)) : \
+ (1UL << channel);
+
+ /* Call analog watchdog callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->AwdCallback(hdfsdm_filter, channel, threshold);
+#else
+ HAL_DFSDM_FilterAwdCallback(hdfsdm_filter, channel, threshold);
+#endif
+ }
+ /* Check if clock absence occurs */
+ else if((hdfsdm_filter->Instance == filter0Instance) && \
+ ((temp_fltisr & DFSDM_FLTISR_CKABF) != 0U) && \
+ ((temp_fltcr2 & DFSDM_FLTCR2_CKABIE) != 0U))
+ {
+ uint32_t reg;
+ uint32_t channel = 0;
+
+ reg = ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_CKABF) >> DFSDM_FLTISR_CKABF_Pos);
+
+ while (channel < channelNumber)
+ {
+ /* Check if flag is set and corresponding channel is enabled */
+ if (((reg & 1U) != 0U) && (channelHandleTable[channel] != NULL))
+ {
+ /* Check clock absence has been enabled for this channel */
+ if ((channelHandleTable[channel]->Instance->CHCFGR1 & DFSDM_CHCFGR1_CKABEN) != 0U)
+ {
+ /* Clear clock absence flag */
+ hdfsdm_filter->Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRCKABF_Pos + channel));
+
+ /* Call clock absence callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ channelHandleTable[channel]->CkabCallback(channelHandleTable[channel]);
+#else
+ HAL_DFSDM_ChannelCkabCallback(channelHandleTable[channel]);
+#endif
+ }
+ }
+ channel++;
+ reg = reg >> 1;
+ }
+ }
+ /* Check if short circuit detection occurs */
+ else if((hdfsdm_filter->Instance == filter0Instance) && \
+ ((temp_fltisr & DFSDM_FLTISR_SCDF) != 0U) && \
+ ((temp_fltcr2 & DFSDM_FLTCR2_SCDIE) != 0U))
+ {
+ uint32_t reg;
+ uint32_t channel = 0;
+
+ /* Get channel */
+ reg = ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_SCDF) >> DFSDM_FLTISR_SCDF_Pos);
+ while (((reg & 1U) == 0U) && (channel < (channelNumber - 1U)))
+ {
+ channel++;
+ reg = reg >> 1;
+ }
+
+ /* Clear short circuit detection flag */
+ hdfsdm_filter->Instance->FLTICR = (1UL << (DFSDM_FLTICR_CLRSCDF_Pos + channel));
+
+ /* Call short circuit detection callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ channelHandleTable[channel]->ScdCallback(channelHandleTable[channel]);
+#else
+ HAL_DFSDM_ChannelScdCallback(channelHandleTable[channel]);
+#endif
+ }
+}
+
+/**
+ * @brief Regular conversion complete callback.
+ * @note In interrupt mode, user has to read conversion value in this function
+ * using HAL_DFSDM_FilterGetRegularValue.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_filter);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DFSDM_FilterRegConvCpltCallback could be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Half regular conversion complete callback.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_filter);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DFSDM_FilterRegConvHalfCpltCallback could be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Injected conversion complete callback.
+ * @note In interrupt mode, user has to read conversion value in this function
+ * using HAL_DFSDM_FilterGetInjectedValue.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_FilterInjConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_filter);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DFSDM_FilterInjConvCpltCallback could be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Half injected conversion complete callback.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_FilterInjConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_filter);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DFSDM_FilterInjConvHalfCpltCallback could be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Filter analog watchdog callback.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @param Channel Corresponding channel.
+ * @param Threshold Low or high threshold has been reached.
+ * @retval None
+ */
+__weak void HAL_DFSDM_FilterAwdCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter,
+ uint32_t Channel, uint32_t Threshold)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_filter);
+ UNUSED(Channel);
+ UNUSED(Threshold);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DFSDM_FilterAwdCallback could be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Error callback.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+__weak void HAL_DFSDM_FilterErrorCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdfsdm_filter);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DFSDM_FilterErrorCallback could be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DFSDM_Exported_Functions_Group4_Filter Filter state functions
+ * @brief Filter state functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Filter state functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Get the DFSDM filter state.
+ (+) Get the DFSDM filter error.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function allows to get the current DFSDM filter handle state.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval DFSDM filter state.
+ */
+HAL_DFSDM_Filter_StateTypeDef HAL_DFSDM_FilterGetState(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Return DFSDM filter handle state */
+ return hdfsdm_filter->State;
+}
+
+/**
+ * @brief This function allows to get the current DFSDM filter error.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval DFSDM filter error code.
+ */
+uint32_t HAL_DFSDM_FilterGetError(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ return hdfsdm_filter->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* End of exported functions -------------------------------------------------*/
+
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup DFSDM_Private_Functions DFSDM Private Functions
+ * @{
+ */
+
+/**
+ * @brief DMA half transfer complete callback for regular conversion.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void DFSDM_DMARegularHalfConvCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Get DFSDM filter handle */
+ DFSDM_Filter_HandleTypeDef *hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Call regular half conversion complete callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->RegConvHalfCpltCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterRegConvHalfCpltCallback(hdfsdm_filter);
+#endif
+}
+
+/**
+ * @brief DMA transfer complete callback for regular conversion.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void DFSDM_DMARegularConvCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Get DFSDM filter handle */
+ DFSDM_Filter_HandleTypeDef *hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Call regular conversion complete callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->RegConvCpltCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterRegConvCpltCallback(hdfsdm_filter);
+#endif
+}
+
+/**
+ * @brief DMA half transfer complete callback for injected conversion.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void DFSDM_DMAInjectedHalfConvCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Get DFSDM filter handle */
+ DFSDM_Filter_HandleTypeDef *hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Call injected half conversion complete callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->InjConvHalfCpltCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterInjConvHalfCpltCallback(hdfsdm_filter);
+#endif
+}
+
+/**
+ * @brief DMA transfer complete callback for injected conversion.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void DFSDM_DMAInjectedConvCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Get DFSDM filter handle */
+ DFSDM_Filter_HandleTypeDef *hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Call injected conversion complete callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->InjConvCpltCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterInjConvCpltCallback(hdfsdm_filter);
+#endif
+}
+
+/**
+ * @brief DMA error callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void DFSDM_DMAError(DMA_HandleTypeDef *hdma)
+{
+ /* Get DFSDM filter handle */
+ DFSDM_Filter_HandleTypeDef *hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Update error code */
+ hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_DMA;
+
+ /* Call error callback */
+#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1)
+ hdfsdm_filter->ErrorCallback(hdfsdm_filter);
+#else
+ HAL_DFSDM_FilterErrorCallback(hdfsdm_filter);
+#endif
+}
+
+/**
+ * @brief This function allows to get the number of injected channels.
+ * @param Channels bitfield of injected channels.
+ * @retval Number of injected channels.
+ */
+static uint32_t DFSDM_GetInjChannelsNbr(uint32_t Channels)
+{
+ uint32_t nbChannels = 0;
+ uint32_t tmp;
+
+ /* Get the number of channels from bitfield */
+ tmp = (uint32_t)(Channels & DFSDM_LSB_MASK);
+ while(tmp != 0U)
+ {
+ if((tmp & 1U) != 0U)
+ {
+ nbChannels++;
+ }
+ tmp = (uint32_t)(tmp >> 1);
+ }
+ return nbChannels;
+}
+
+/**
+ * @brief This function allows to get the channel number from channel instance.
+ * @param Instance DFSDM channel instance.
+ * @retval Channel number.
+ */
+static uint32_t DFSDM_GetChannelFromInstance(const DFSDM_Channel_TypeDef* Instance)
+{
+ uint32_t channel;
+
+ /* Get channel from instance */
+ if(Instance == DFSDM1_Channel0)
+ {
+ channel = 0;
+ }
+#if defined(DFSDM2_Channel0)
+ else if (Instance == DFSDM2_Channel0)
+ {
+ channel = 0;
+ }
+ else if (Instance == DFSDM2_Channel1)
+ {
+ channel = 1;
+ }
+#endif /* DFSDM2_Channel0 */
+ else if(Instance == DFSDM1_Channel1)
+ {
+ channel = 1;
+ }
+ else if(Instance == DFSDM1_Channel2)
+ {
+ channel = 2;
+ }
+ else if(Instance == DFSDM1_Channel3)
+ {
+ channel = 3;
+ }
+ else if(Instance == DFSDM1_Channel4)
+ {
+ channel = 4;
+ }
+ else if(Instance == DFSDM1_Channel5)
+ {
+ channel = 5;
+ }
+ else if(Instance == DFSDM1_Channel6)
+ {
+ channel = 6;
+ }
+ else /* DFSDM1_Channel7 */
+ {
+ channel = 7;
+ }
+
+ return channel;
+}
+
+/**
+ * @brief This function allows to really start regular conversion.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+static void DFSDM_RegConvStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Check regular trigger */
+ if(hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER)
+ {
+ /* Software start of regular conversion */
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RSWSTART;
+ }
+ else /* synchronous trigger */
+ {
+ /* Disable DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN);
+
+ /* Set RSYNC bit in DFSDM_FLTCR1 register */
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RSYNC;
+
+ /* Enable DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN;
+
+ /* If injected conversion was in progress, restart it */
+ if(hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ)
+ {
+ if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER)
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSWSTART;
+ }
+ /* Update remaining injected conversions */
+ hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \
+ hdfsdm_filter->InjectedChannelsNbr : 1U;
+ }
+ }
+ /* Update DFSDM filter state */
+ hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) ? \
+ HAL_DFSDM_FILTER_STATE_REG : HAL_DFSDM_FILTER_STATE_REG_INJ;
+}
+
+/**
+ * @brief This function allows to really stop regular conversion.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+static void DFSDM_RegConvStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Disable DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN);
+
+ /* If regular trigger was synchronous, reset RSYNC bit in DFSDM_FLTCR1 register */
+ if(hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SYNC_TRIGGER)
+ {
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_RSYNC);
+ }
+
+ /* Enable DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN;
+
+ /* If injected conversion was in progress, restart it */
+ if(hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG_INJ)
+ {
+ if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER)
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSWSTART;
+ }
+ /* Update remaining injected conversions */
+ hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \
+ hdfsdm_filter->InjectedChannelsNbr : 1U;
+ }
+
+ /* Update DFSDM filter state */
+ hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG) ? \
+ HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_INJ;
+}
+
+/**
+ * @brief This function allows to really start injected conversion.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+static void DFSDM_InjConvStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Check injected trigger */
+ if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER)
+ {
+ /* Software start of injected conversion */
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSWSTART;
+ }
+ else /* external or synchronous trigger */
+ {
+ /* Disable DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN);
+
+ if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SYNC_TRIGGER)
+ {
+ /* Set JSYNC bit in DFSDM_FLTCR1 register */
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSYNC;
+ }
+ else /* external trigger */
+ {
+ /* Set JEXTEN[1:0] bits in DFSDM_FLTCR1 register */
+ hdfsdm_filter->Instance->FLTCR1 |= hdfsdm_filter->ExtTriggerEdge;
+ }
+
+ /* Enable DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN;
+
+ /* If regular conversion was in progress, restart it */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG) && \
+ (hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER))
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RSWSTART;
+ }
+ }
+ /* Update DFSDM filter state */
+ hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) ? \
+ HAL_DFSDM_FILTER_STATE_INJ : HAL_DFSDM_FILTER_STATE_REG_INJ;
+}
+
+/**
+ * @brief This function allows to really stop injected conversion.
+ * @param hdfsdm_filter DFSDM filter handle.
+ * @retval None
+ */
+static void DFSDM_InjConvStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+ /* Disable DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN);
+
+ /* If injected trigger was synchronous, reset JSYNC bit in DFSDM_FLTCR1 register */
+ if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SYNC_TRIGGER)
+ {
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JSYNC);
+ }
+ else if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_EXT_TRIGGER)
+ {
+ /* Reset JEXTEN[1:0] bits in DFSDM_FLTCR1 register */
+ hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JEXTEN);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Enable DFSDM filter */
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN;
+
+ /* If regular conversion was in progress, restart it */
+ if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG_INJ) && \
+ (hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER))
+ {
+ hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RSWSTART;
+ }
+
+ /* Update remaining injected conversions */
+ hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \
+ hdfsdm_filter->InjectedChannelsNbr : 1U;
+
+ /* Update DFSDM filter state */
+ hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ) ? \
+ HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_REG;
+}
+
+/**
+ * @}
+ */
+/* End of private functions --------------------------------------------------*/
+
+/**
+ * @}
+ */
+
+#endif /* HAL_DFSDM_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dfsdm_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dfsdm_ex.c
new file mode 100644
index 0000000000..e0349b4a47
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dfsdm_ex.c
@@ -0,0 +1,135 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dfsdm_ex.c
+ * @author MCD Application Team
+ * @brief DFSDM Extended HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionality of the DFSDM Peripheral Controller:
+ * + Set and get pulses skipping on channel.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_DFSDM_MODULE_ENABLED
+
+#if defined(DFSDM_CHDLYR_PLSSKP)
+
+/** @defgroup DFSDMEx DFSDMEx
+ * @brief DFSDM Extended HAL module driver
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup DFSDMEx_Exported_Functions DFSDM Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup DFSDMEx_Exported_Functions_Group1_Channel Extended channel operation functions
+ * @brief DFSDM extended channel operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended channel operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Set and get value of pulses skipping on channel
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set value of pulses skipping.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @param PulsesValue Value of pulses to be skipped.
+ * This parameter must be a number between Min_Data = 0 and Max_Data = 63.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFDSMEx_ChannelSetPulsesSkipping(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, uint32_t PulsesValue)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check pulses value */
+ assert_param(IS_DFSDM_CHANNEL_SKIPPING_VALUE(PulsesValue));
+
+ /* Check DFSDM channel state */
+ if (hdfsdm_channel->State == HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Set new value of pulses skipping */
+ hdfsdm_channel->Instance->CHDLYR = (PulsesValue & DFSDM_CHDLYR_PLSSKP);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ return status;
+}
+
+/**
+ * @brief Get value of pulses skipping.
+ * @param hdfsdm_channel DFSDM channel handle.
+ * @param PulsesValue Value of pulses to be skipped.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_DFDSMEx_ChannelGetPulsesSkipping(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, uint32_t *PulsesValue)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check DFSDM channel state */
+ if (hdfsdm_channel->State == HAL_DFSDM_CHANNEL_STATE_READY)
+ {
+ /* Get value of remaining pulses to be skipped */
+ *PulsesValue = (hdfsdm_channel->Instance->CHDLYR & DFSDM_CHDLYR_PLSSKP);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* DFSDM_CHDLYR_PLSSKP */
+
+#endif /* HAL_DFSDM_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dma.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dma.c
new file mode 100644
index 0000000000..e2bbea732e
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dma.c
@@ -0,0 +1,2055 @@
+/**
+ ******************************************************************************
+ * @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
+ @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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DMA DMA
+ * @brief DMA HAL module driver
+ * @{
+ */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+
+/* 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(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));
+ }
+
+ /* Allocate lock resource */
+ __HAL_UNLOCK(hdma);
+
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* 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 transfering data to/from USART/UART */
+#if (STM32H7_DEV_ID == 0x450UL)
+ if((DBGMCU->IDCODE & 0xFFFF0000U) >= 0x20000000U)
+ {
+#endif /* STM32H7_DEV_ID == 0x450UL */
+ if(IS_DMA_UART_USART_REQUEST(hdma->Init.Request) != 0U)
+ {
+ registerValue |= DMA_SxCR_TRBUFF;
+ }
+#if (STM32H7_DEV_ID == 0x450UL)
+ }
+#endif /* STM32H7_DEV_ID == 0x450UL */
+
+ /* 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));
+ }
+
+ /* Allocate lock resource */
+ __HAL_UNLOCK(hdma);
+
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* 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(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->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
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Set the error code to busy */
+ hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
+
+ /* 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
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Set the error code to busy */
+ hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
+
+ /* 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 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;
+ }
+
+ /* Disable the stream */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* 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;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_ERROR;
+
+ 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;
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+ }
+
+ 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 DMA All Interrupts */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR &= ~(BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE);
+
+ /* Disable the channel */
+ __HAL_DMA_DISABLE(hdma);
+
+ 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;
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* 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 recommanded 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));
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ hdma->State = HAL_DMA_STATE_READY;
+ }
+ 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);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ 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 0 */
+ 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 1 */
+ 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);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+ }
+
+ 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);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ 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;
+ }
+ }
+
+ 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 0 */
+ 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 1 */
+ 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);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+ }
+
+ 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;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ 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:
+ 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(DMA_HandleTypeDef *hdma)
+{
+ return hdma->State;
+}
+
+/**
+ * @brief Return the DMA error code
+ * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval DMA Error Code
+ */
+uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
+{
+ return hdma->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @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;
+
+ /* 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 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;
+
+ /* Peripheral to Memory */
+ 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;
+ }
+ /* Memory to Peripheral */
+ 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(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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dma2d.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dma2d.c
new file mode 100644
index 0000000000..b6b8d4099d
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dma2d.c
@@ -0,0 +1,2167 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dma2d.c
+ * @author MCD Application Team
+ * @brief DMA2D HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the DMA2D peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Program the required configuration through the following parameters:
+ the transfer mode, the output color mode and the output offset using
+ HAL_DMA2D_Init() function.
+
+ (#) Program the required configuration through the following parameters:
+ the input color mode, the input color, the input alpha value, the alpha mode,
+ the red/blue swap mode, the inverted alpha mode and the input offset using
+ HAL_DMA2D_ConfigLayer() function for foreground or/and background layer.
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (#) Configure pdata parameter (explained hereafter), destination and data length
+ and enable the transfer using HAL_DMA2D_Start().
+ (#) Wait for end of transfer using HAL_DMA2D_PollForTransfer(), at this stage
+ user can specify the value of timeout according to his end application.
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (#) Configure pdata parameter, destination and data length and enable
+ the transfer using HAL_DMA2D_Start_IT().
+ (#) Use HAL_DMA2D_IRQHandler() called under DMA2D_IRQHandler() interrupt subroutine.
+ (#) At the end of data transfer HAL_DMA2D_IRQHandler() function is executed and user can
+ add his own function by customization of function pointer XferCpltCallback (member
+ of DMA2D handle structure).
+ (#) In case of error, the HAL_DMA2D_IRQHandler() function calls the callback
+ XferErrorCallback.
+
+ -@- In Register-to-Memory transfer mode, pdata parameter is the register
+ color, in Memory-to-memory or Memory-to-Memory with pixel format
+ conversion pdata is the source address.
+
+ -@- Configure the foreground source address, the background source address,
+ the destination and data length then Enable the transfer using
+ HAL_DMA2D_BlendingStart() in polling mode and HAL_DMA2D_BlendingStart_IT()
+ in interrupt mode.
+
+ -@- HAL_DMA2D_BlendingStart() and HAL_DMA2D_BlendingStart_IT() functions
+ are used if the memory to memory with blending transfer mode is selected.
+
+ (#) Optionally, configure and enable the CLUT using HAL_DMA2D_CLUTLoad() in polling
+ mode or HAL_DMA2D_CLUTLoad_IT() in interrupt mode.
+
+ (#) Optionally, configure the line watermark in using the API HAL_DMA2D_ProgramLineEvent().
+
+ (#) Optionally, configure the dead time value in the AHB clock cycle inserted between two
+ consecutive accesses on the AHB master port in using the API HAL_DMA2D_ConfigDeadTime()
+ and enable/disable the functionality with the APIs HAL_DMA2D_EnableDeadTime() or
+ HAL_DMA2D_DisableDeadTime().
+
+ (#) The transfer can be suspended, resumed and aborted using the following
+ functions: HAL_DMA2D_Suspend(), HAL_DMA2D_Resume(), HAL_DMA2D_Abort().
+
+ (#) The CLUT loading can be suspended, resumed and aborted using the following
+ functions: HAL_DMA2D_CLUTLoading_Suspend(), HAL_DMA2D_CLUTLoading_Resume(),
+ HAL_DMA2D_CLUTLoading_Abort().
+
+ (#) To control the DMA2D state, use the following function: HAL_DMA2D_GetState().
+
+ (#) To read the DMA2D error code, use the following function: HAL_DMA2D_GetError().
+
+ *** DMA2D HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in DMA2D HAL driver :
+
+ (+) __HAL_DMA2D_ENABLE: Enable the DMA2D peripheral.
+ (+) __HAL_DMA2D_GET_FLAG: Get the DMA2D pending flags.
+ (+) __HAL_DMA2D_CLEAR_FLAG: Clear the DMA2D pending flags.
+ (+) __HAL_DMA2D_ENABLE_IT: Enable the specified DMA2D interrupts.
+ (+) __HAL_DMA2D_DISABLE_IT: Disable the specified DMA2D interrupts.
+ (+) __HAL_DMA2D_GET_IT_SOURCE: Check whether the specified DMA2D interrupt is enabled or not.
+
+ *** Callback registration ***
+ ===================================
+ [..]
+ (#) The compilation define USE_HAL_DMA2D_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use function @ref HAL_DMA2D_RegisterCallback() to register a user callback.
+
+ (#) Function @ref HAL_DMA2D_RegisterCallback() allows to register following callbacks:
+ (+) XferCpltCallback : callback for transfer complete.
+ (+) XferErrorCallback : callback for transfer error.
+ (+) LineEventCallback : callback for line event.
+ (+) CLUTLoadingCpltCallback : callback for CLUT loading completion.
+ (+) MspInitCallback : DMA2D MspInit.
+ (+) MspDeInitCallback : DMA2D MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ (#) Use function @ref HAL_DMA2D_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function.
+ @ref HAL_DMA2D_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) XferCpltCallback : callback for transfer complete.
+ (+) XferErrorCallback : callback for transfer error.
+ (+) LineEventCallback : callback for line event.
+ (+) CLUTLoadingCpltCallback : callback for CLUT loading completion.
+ (+) MspInitCallback : DMA2D MspInit.
+ (+) MspDeInitCallback : DMA2D MspDeInit.
+
+ (#) By default, after the @ref HAL_DMA2D_Init and if the state is HAL_DMA2D_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions:
+ examples @ref HAL_DMA2D_LineEventCallback(), @ref HAL_DMA2D_CLUTLoadingCpltCallback()
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_DMA2D_Init
+ and @ref HAL_DMA2D_DeInit only when these callbacks are null (not registered beforehand)
+ If not, MspInit or MspDeInit are not null, the @ref HAL_DMA2D_Init and @ref HAL_DMA2D_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
+
+ Exception as well for Transfer Completion and Transfer Error callbacks that are not defined
+ as weak (surcharged) functions. They must be defined by the user to be resorted to.
+
+ 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 @ref HAL_DMA2D_RegisterCallback before calling @ref HAL_DMA2D_DeInit
+ or @ref HAL_DMA2D_Init function.
+
+ When The compilation define USE_HAL_DMA2D_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ [..]
+ (@) You can refer to the DMA2D HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+#ifdef HAL_DMA2D_MODULE_ENABLED
+#if defined (DMA2D)
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DMA2D DMA2D
+ * @brief DMA2D HAL module driver
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup DMA2D_Private_Constants DMA2D Private Constants
+ * @{
+ */
+
+/** @defgroup DMA2D_TimeOut DMA2D Time Out
+ * @{
+ */
+#define DMA2D_TIMEOUT_ABORT (1000U) /*!< 1s */
+#define DMA2D_TIMEOUT_SUSPEND (1000U) /*!< 1s */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup DMA2D_Private_Functions DMA2D Private Functions
+ * @{
+ */
+static void DMA2D_SetConfig(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, uint32_t Height);
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup DMA2D_Exported_Functions DMA2D Exported Functions
+ * @{
+ */
+
+/** @defgroup DMA2D_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the DMA2D
+ (+) De-initialize the DMA2D
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the DMA2D according to the specified
+ * parameters in the DMA2D_InitTypeDef and create the associated handle.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_Init(DMA2D_HandleTypeDef *hdma2d)
+{
+ /* Check the DMA2D peripheral state */
+ if(hdma2d == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_DMA2D_ALL_INSTANCE(hdma2d->Instance));
+ assert_param(IS_DMA2D_MODE(hdma2d->Init.Mode));
+ assert_param(IS_DMA2D_CMODE(hdma2d->Init.ColorMode));
+ assert_param(IS_DMA2D_OFFSET(hdma2d->Init.OutputOffset));
+ assert_param(IS_DMA2D_ALPHA_INVERTED(hdma2d->Init.AlphaInverted));
+ assert_param(IS_DMA2D_RB_SWAP(hdma2d->Init.RedBlueSwap));
+ assert_param(IS_DMA2D_LOM_MODE(hdma2d->Init.LineOffsetMode));
+ assert_param(IS_DMA2D_BYTES_SWAP(hdma2d->Init.BytesSwap));
+
+#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1)
+ if (hdma2d->State == HAL_DMA2D_STATE_RESET)
+ {
+ /* Reset Callback pointers in HAL_DMA2D_STATE_RESET only */
+ hdma2d->LineEventCallback = HAL_DMA2D_LineEventCallback;
+ hdma2d->CLUTLoadingCpltCallback = HAL_DMA2D_CLUTLoadingCpltCallback;
+ if(hdma2d->MspInitCallback == NULL)
+ {
+ hdma2d->MspInitCallback = HAL_DMA2D_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hdma2d->MspInitCallback(hdma2d);
+ }
+#else
+ if(hdma2d->State == HAL_DMA2D_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hdma2d->Lock = HAL_UNLOCKED;
+ /* Init the low level hardware */
+ HAL_DMA2D_MspInit(hdma2d);
+ }
+#endif /* (USE_HAL_DMA2D_REGISTER_CALLBACKS) */
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* DMA2D CR register configuration -------------------------------------------*/
+ MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_MODE | DMA2D_CR_LOM, hdma2d->Init.Mode | hdma2d->Init.LineOffsetMode);
+
+ /* DMA2D OPFCCR register configuration ---------------------------------------*/
+ MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_CM | DMA2D_OPFCCR_SB, hdma2d->Init.ColorMode | hdma2d->Init.BytesSwap);
+
+ /* DMA2D OOR register configuration ------------------------------------------*/
+ MODIFY_REG(hdma2d->Instance->OOR, DMA2D_OOR_LO, hdma2d->Init.OutputOffset);
+ /* DMA2D OPFCCR AI and RBS fields setting (Output Alpha Inversion)*/
+ MODIFY_REG(hdma2d->Instance->OPFCCR,(DMA2D_OPFCCR_AI|DMA2D_OPFCCR_RBS), ((hdma2d->Init.AlphaInverted << DMA2D_OPFCCR_AI_Pos) | (hdma2d->Init.RedBlueSwap << DMA2D_OPFCCR_RBS_Pos)));
+
+
+ /* Update error code */
+ hdma2d->ErrorCode = HAL_DMA2D_ERROR_NONE;
+
+ /* Initialize the DMA2D state*/
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deinitializes the DMA2D peripheral registers to their default reset
+ * values.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval None
+ */
+
+HAL_StatusTypeDef HAL_DMA2D_DeInit(DMA2D_HandleTypeDef *hdma2d)
+{
+
+ /* Check the DMA2D peripheral state */
+ if(hdma2d == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Before aborting any DMA2D transfer or CLUT loading, check
+ first whether or not DMA2D clock is enabled */
+ if (__HAL_RCC_DMA2D_IS_CLK_ENABLED())
+ {
+ /* Abort DMA2D transfer if any */
+ if ((hdma2d->Instance->CR & DMA2D_CR_START) == DMA2D_CR_START)
+ {
+ if (HAL_DMA2D_Abort(hdma2d) != HAL_OK)
+ {
+ /* Issue when aborting DMA2D transfer */
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Abort background CLUT loading if any */
+ if ((hdma2d->Instance->BGPFCCR & DMA2D_BGPFCCR_START) == DMA2D_BGPFCCR_START)
+ {
+ if (HAL_DMA2D_CLUTLoading_Abort(hdma2d, 0U) != HAL_OK)
+ {
+ /* Issue when aborting background CLUT loading */
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Abort foreground CLUT loading if any */
+ if ((hdma2d->Instance->FGPFCCR & DMA2D_FGPFCCR_START) == DMA2D_FGPFCCR_START)
+ {
+ if (HAL_DMA2D_CLUTLoading_Abort(hdma2d, 1U) != HAL_OK)
+ {
+ /* Issue when aborting foreground CLUT loading */
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+ }
+
+ /* Reset DMA2D control registers*/
+ hdma2d->Instance->CR = 0U;
+ hdma2d->Instance->IFCR = 0x3FU;
+ hdma2d->Instance->FGOR = 0U;
+ hdma2d->Instance->BGOR = 0U;
+ hdma2d->Instance->FGPFCCR = 0U;
+ hdma2d->Instance->BGPFCCR = 0U;
+ hdma2d->Instance->OPFCCR = 0U;
+
+#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1)
+
+ if(hdma2d->MspDeInitCallback == NULL)
+ {
+ hdma2d->MspDeInitCallback = HAL_DMA2D_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hdma2d->MspDeInitCallback(hdma2d);
+
+#else
+ /* Carry on with de-initialization of low level hardware */
+ HAL_DMA2D_MspDeInit(hdma2d);
+#endif /* (USE_HAL_DMA2D_REGISTER_CALLBACKS) */
+
+ /* Update error code */
+ hdma2d->ErrorCode = HAL_DMA2D_ERROR_NONE;
+
+ /* Initialize the DMA2D state*/
+ hdma2d->State = HAL_DMA2D_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the DMA2D MSP.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval None
+ */
+__weak void HAL_DMA2D_MspInit(DMA2D_HandleTypeDef* hdma2d)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdma2d);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ the HAL_DMA2D_MspInit can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief DeInitializes the DMA2D MSP.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval None
+ */
+__weak void HAL_DMA2D_MspDeInit(DMA2D_HandleTypeDef* hdma2d)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdma2d);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ the HAL_DMA2D_MspDeInit can be implemented in the user file.
+ */
+}
+
+#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User DMA2D Callback
+ * To be used instead of the weak (surcharged) predefined callback
+ * @param hdma2d DMA2D handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DMA2D_TRANSFERCOMPLETE_CB_ID DMA2D transfer complete Callback ID
+ * @arg @ref HAL_DMA2D_TRANSFERERROR_CB_ID DMA2D transfer error Callback ID
+ * @arg @ref HAL_DMA2D_LINEEVENT_CB_ID DMA2D line event Callback ID
+ * @arg @ref HAL_DMA2D_CLUTLOADINGCPLT_CB_ID DMA2D CLUT loading completion Callback ID
+ * @arg @ref HAL_DMA2D_MSPINIT_CB_ID DMA2D MspInit callback ID
+ * @arg @ref HAL_DMA2D_MSPDEINIT_CB_ID DMA2D MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @note No weak predefined callbacks are defined for HAL_DMA2D_TRANSFERCOMPLETE_CB_ID or HAL_DMA2D_TRANSFERERROR_CB_ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_DMA2D_RegisterCallback(DMA2D_HandleTypeDef *hdma2d, HAL_DMA2D_CallbackIDTypeDef CallbackID, pDMA2D_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ if(HAL_DMA2D_STATE_READY == hdma2d->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DMA2D_TRANSFERCOMPLETE_CB_ID :
+ hdma2d->XferCpltCallback = pCallback;
+ break;
+
+ case HAL_DMA2D_TRANSFERERROR_CB_ID :
+ hdma2d->XferErrorCallback = pCallback;
+ break;
+
+ case HAL_DMA2D_LINEEVENT_CB_ID :
+ hdma2d->LineEventCallback = pCallback;
+ break;
+
+ case HAL_DMA2D_CLUTLOADINGCPLT_CB_ID :
+ hdma2d->CLUTLoadingCpltCallback = pCallback;
+ break;
+
+ case HAL_DMA2D_MSPINIT_CB_ID :
+ hdma2d->MspInitCallback = pCallback;
+ break;
+
+ case HAL_DMA2D_MSPDEINIT_CB_ID :
+ hdma2d->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_DMA2D_STATE_RESET == hdma2d->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DMA2D_MSPINIT_CB_ID :
+ hdma2d->MspInitCallback = pCallback;
+ break;
+
+ case HAL_DMA2D_MSPDEINIT_CB_ID :
+ hdma2d->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdma2d);
+ return status;
+}
+
+/**
+ * @brief Unregister a DMA2D Callback
+ * DMA2D Callback is redirected to the weak (surcharged) predefined callback
+ * @param hdma2d DMA2D handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_DMA2D_TRANSFERCOMPLETE_CB_ID DMA2D transfer complete Callback ID
+ * @arg @ref HAL_DMA2D_TRANSFERERROR_CB_ID DMA2D transfer error Callback ID
+ * @arg @ref HAL_DMA2D_LINEEVENT_CB_ID DMA2D line event Callback ID
+ * @arg @ref HAL_DMA2D_CLUTLOADINGCPLT_CB_ID DMA2D CLUT loading completion Callback ID
+ * @arg @ref HAL_DMA2D_MSPINIT_CB_ID DMA2D MspInit callback ID
+ * @arg @ref HAL_DMA2D_MSPDEINIT_CB_ID DMA2D MspDeInit callback ID
+ * @note No weak predefined callbacks are defined for HAL_DMA2D_TRANSFERCOMPLETE_CB_ID or HAL_DMA2D_TRANSFERERROR_CB_ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_DMA2D_UnRegisterCallback(DMA2D_HandleTypeDef *hdma2d, HAL_DMA2D_CallbackIDTypeDef CallbackID)
+{
+HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ if(HAL_DMA2D_STATE_READY == hdma2d->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DMA2D_TRANSFERCOMPLETE_CB_ID :
+ hdma2d->XferCpltCallback = NULL;
+ break;
+
+ case HAL_DMA2D_TRANSFERERROR_CB_ID :
+ hdma2d->XferErrorCallback = NULL;
+ break;
+
+ case HAL_DMA2D_LINEEVENT_CB_ID :
+ hdma2d->LineEventCallback = HAL_DMA2D_LineEventCallback;
+ break;
+
+ case HAL_DMA2D_CLUTLOADINGCPLT_CB_ID :
+ hdma2d->CLUTLoadingCpltCallback = HAL_DMA2D_CLUTLoadingCpltCallback;
+ break;
+
+ case HAL_DMA2D_MSPINIT_CB_ID :
+ hdma2d->MspInitCallback = HAL_DMA2D_MspInit; /* Legacy weak (surcharged) Msp Init */
+ break;
+
+ case HAL_DMA2D_MSPDEINIT_CB_ID :
+ hdma2d->MspDeInitCallback = HAL_DMA2D_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_DMA2D_STATE_RESET == hdma2d->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DMA2D_MSPINIT_CB_ID :
+ hdma2d->MspInitCallback = HAL_DMA2D_MspInit; /* Legacy weak (surcharged) Msp Init */
+ break;
+
+ case HAL_DMA2D_MSPDEINIT_CB_ID :
+ hdma2d->MspDeInitCallback = HAL_DMA2D_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdma2d);
+ return status;
+}
+#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup DMA2D_Exported_Functions_Group2 IO operation functions
+ * @brief IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure the pdata, destination address and data size then
+ start the DMA2D transfer.
+ (+) Configure the source for foreground and background, destination address
+ and data size then start a MultiBuffer DMA2D transfer.
+ (+) Configure the pdata, destination address and data size then
+ start the DMA2D transfer with interrupt.
+ (+) Configure the source for foreground and background, destination address
+ and data size then start a MultiBuffer DMA2D transfer with interrupt.
+ (+) Abort DMA2D transfer.
+ (+) Suspend DMA2D transfer.
+ (+) Resume DMA2D transfer.
+ (+) Enable CLUT transfer.
+ (+) Configure CLUT loading then start transfer in polling mode.
+ (+) Configure CLUT loading then start transfer in interrupt mode.
+ (+) Abort DMA2D CLUT loading.
+ (+) Suspend DMA2D CLUT loading.
+ (+) Resume DMA2D CLUT loading.
+ (+) Poll for transfer complete.
+ (+) handle DMA2D interrupt request.
+ (+) Transfer watermark callback.
+ (+) CLUT Transfer Complete callback.
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the DMA2D Transfer.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param pdata Configure the source memory Buffer address if
+ * Memory-to-Memory or Memory-to-Memory with pixel format
+ * conversion mode is selected, or configure
+ * the color value if Register-to-Memory mode is selected.
+ * @param DstAddress The destination memory Buffer address.
+ * @param Width The width of data to be transferred from source to destination (expressed in number of pixels per line).
+ * @param Height The height of data to be transferred from source to destination (expressed in number of lines).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_Start(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, uint32_t Height)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LINE(Height));
+ assert_param(IS_DMA2D_PIXEL(Width));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Configure the source, destination address and the data size */
+ DMA2D_SetConfig(hdma2d, pdata, DstAddress, Width, Height);
+
+ /* Enable the Peripheral */
+ __HAL_DMA2D_ENABLE(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the DMA2D Transfer with interrupt enabled.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param pdata Configure the source memory Buffer address if
+ * the Memory-to-Memory or Memory-to-Memory with pixel format
+ * conversion mode is selected, or configure
+ * the color value if Register-to-Memory mode is selected.
+ * @param DstAddress The destination memory Buffer address.
+ * @param Width The width of data to be transferred from source to destination (expressed in number of pixels per line).
+ * @param Height The height of data to be transferred from source to destination (expressed in number of lines).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_Start_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, uint32_t Height)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LINE(Height));
+ assert_param(IS_DMA2D_PIXEL(Width));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Configure the source, destination address and the data size */
+ DMA2D_SetConfig(hdma2d, pdata, DstAddress, Width, Height);
+
+ /* Enable the transfer complete, transfer error and configuration error interrupts */
+ __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE);
+
+ /* Enable the Peripheral */
+ __HAL_DMA2D_ENABLE(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the multi-source DMA2D Transfer.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param SrcAddress1 The source memory Buffer address for the foreground layer.
+ * @param SrcAddress2 The source memory Buffer address for the background layer.
+ * @param DstAddress The destination memory Buffer address.
+ * @param Width The width of data to be transferred from source to destination (expressed in number of pixels per line).
+ * @param Height The height of data to be transferred from source to destination (expressed in number of lines).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_BlendingStart(DMA2D_HandleTypeDef *hdma2d, uint32_t SrcAddress1, uint32_t SrcAddress2, uint32_t DstAddress, uint32_t Width, uint32_t Height)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LINE(Height));
+ assert_param(IS_DMA2D_PIXEL(Width));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ if(hdma2d->Init.Mode == DMA2D_M2M_BLEND_FG)
+ {
+ /*blending & fixed FG*/
+ WRITE_REG(hdma2d->Instance->FGCOLR, SrcAddress1);
+ /* Configure the source, destination address and the data size */
+ DMA2D_SetConfig(hdma2d, SrcAddress2, DstAddress, Width, Height);
+ }
+ else if (hdma2d->Init.Mode == DMA2D_M2M_BLEND_BG)
+ {
+ /*blending & fixed BG*/
+ WRITE_REG(hdma2d->Instance->BGCOLR, SrcAddress2);
+ /* Configure the source, destination address and the data size */
+ DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height);
+ }
+ else
+ {
+ /* Configure DMA2D Stream source2 address */
+ WRITE_REG(hdma2d->Instance->BGMAR, SrcAddress2);
+
+ /* Configure the source, destination address and the data size */
+ DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height);
+ }
+
+ /* Enable the Peripheral */
+ __HAL_DMA2D_ENABLE(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the multi-source DMA2D Transfer with interrupt enabled.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param SrcAddress1 The source memory Buffer address for the foreground layer.
+ * @param SrcAddress2 The source memory Buffer address for the background layer.
+ * @param DstAddress The destination memory Buffer address.
+ * @param Width The width of data to be transferred from source to destination (expressed in number of pixels per line).
+ * @param Height The height of data to be transferred from source to destination (expressed in number of lines).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_BlendingStart_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t SrcAddress1, uint32_t SrcAddress2, uint32_t DstAddress, uint32_t Width, uint32_t Height)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LINE(Height));
+ assert_param(IS_DMA2D_PIXEL(Width));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ if(hdma2d->Init.Mode == DMA2D_M2M_BLEND_FG)
+ {
+ /*blending & fixed FG*/
+ WRITE_REG(hdma2d->Instance->FGCOLR, SrcAddress1);
+ /* Configure the source, destination address and the data size */
+ DMA2D_SetConfig(hdma2d, SrcAddress2, DstAddress, Width, Height);
+ }
+ else if (hdma2d->Init.Mode == DMA2D_M2M_BLEND_BG)
+ {
+ /*blending & fixed BG*/
+ WRITE_REG(hdma2d->Instance->BGCOLR, SrcAddress2);
+ /* Configure the source, destination address and the data size */
+ DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height);
+ }
+ else
+ {
+ WRITE_REG(hdma2d->Instance->BGMAR, SrcAddress2);
+
+ /* Configure the source, destination address and the data size */
+ DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height);
+ }
+
+ /* Enable the transfer complete, transfer error and configuration error interrupts */
+ __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE);
+
+ /* Enable the Peripheral */
+ __HAL_DMA2D_ENABLE(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort the DMA2D Transfer.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_Abort(DMA2D_HandleTypeDef *hdma2d)
+{
+ uint32_t tickstart;
+
+ /* Abort the DMA2D transfer */
+ /* START bit is reset to make sure not to set it again, in the event the HW clears it
+ between the register read and the register write by the CPU (writing 0 has no
+ effect on START bitvalue) */
+ MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_ABORT|DMA2D_CR_START, DMA2D_CR_ABORT);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check if the DMA2D is effectively disabled */
+ while((hdma2d->Instance->CR & DMA2D_CR_START) != 0U)
+ {
+ if((HAL_GetTick() - tickstart ) > DMA2D_TIMEOUT_ABORT)
+ {
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT;
+
+ /* Change the DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Disable the Transfer Complete, Transfer Error and Configuration Error interrupts */
+ __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE);
+
+ /* Change the DMA2D state*/
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Suspend the DMA2D Transfer.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_Suspend(DMA2D_HandleTypeDef *hdma2d)
+{
+ uint32_t tickstart;
+
+ /* Suspend the DMA2D transfer */
+ /* START bit is reset to make sure not to set it again, in the event the HW clears it
+ between the register read and the register write by the CPU (writing 0 has no
+ effect on START bitvalue). */
+ MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_SUSP|DMA2D_CR_START, DMA2D_CR_SUSP);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check if the DMA2D is effectively suspended */
+ while ((hdma2d->Instance->CR & (DMA2D_CR_SUSP | DMA2D_CR_START)) == DMA2D_CR_START)
+ {
+ if((HAL_GetTick() - tickstart ) > DMA2D_TIMEOUT_SUSPEND)
+ {
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT;
+
+ /* Change the DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check whether or not a transfer is actually suspended and change the DMA2D state accordingly */
+ if ((hdma2d->Instance->CR & DMA2D_CR_START) != 0U)
+ {
+ hdma2d->State = HAL_DMA2D_STATE_SUSPEND;
+ }
+ else
+ {
+ /* Make sure SUSP bit is cleared since it is meaningless
+ when no tranfer is on-going */
+ CLEAR_BIT(hdma2d->Instance->CR, DMA2D_CR_SUSP);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the DMA2D Transfer.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_Resume(DMA2D_HandleTypeDef *hdma2d)
+{
+ /* Check the SUSP and START bits */
+ if((hdma2d->Instance->CR & (DMA2D_CR_SUSP | DMA2D_CR_START)) == (DMA2D_CR_SUSP | DMA2D_CR_START))
+ {
+ /* Ongoing transfer is suspended: change the DMA2D state before resuming */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+ }
+
+ /* Resume the DMA2D transfer */
+ /* START bit is reset to make sure not to set it again, in the event the HW clears it
+ between the register read and the register write by the CPU (writing 0 has no
+ effect on START bitvalue). */
+ CLEAR_BIT(hdma2d->Instance->CR, (DMA2D_CR_SUSP|DMA2D_CR_START));
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Enable the DMA2D CLUT Transfer.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_EnableCLUT(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ if(LayerIdx == DMA2D_BACKGROUND_LAYER)
+ {
+ /* Enable the background CLUT loading */
+ SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START);
+ }
+ else
+ {
+ /* Enable the foreground CLUT loading */
+ SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start DMA2D CLUT Loading.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains
+ * the configuration information for the color look up table.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_CLUTStartLoad(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef *CLUTCfg, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LAYER(LayerIdx));
+ assert_param(IS_DMA2D_CLUT_CM(CLUTCfg->CLUTColorMode));
+ assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg->Size));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Configure the CLUT of the background DMA2D layer */
+ if(LayerIdx == DMA2D_BACKGROUND_LAYER)
+ {
+ /* Write background CLUT memory address */
+ WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg->pCLUT);
+
+ /* Write background CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM),
+ ((CLUTCfg->Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg->CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos)));
+
+ /* Enable the CLUT loading for the background */
+ SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START);
+ }
+ /* Configure the CLUT of the foreground DMA2D layer */
+ else
+ {
+ /* Write foreground CLUT memory address */
+ WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg->pCLUT);
+
+ /* Write foreground CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM),
+ ((CLUTCfg->Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg->CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos)));
+
+ /* Enable the CLUT loading for the foreground */
+ SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start DMA2D CLUT Loading with interrupt enabled.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains
+ * the configuration information for the color look up table.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_CLUTStartLoad_IT(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef *CLUTCfg, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LAYER(LayerIdx));
+ assert_param(IS_DMA2D_CLUT_CM(CLUTCfg->CLUTColorMode));
+ assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg->Size));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Configure the CLUT of the background DMA2D layer */
+ if(LayerIdx == DMA2D_BACKGROUND_LAYER)
+ {
+ /* Write background CLUT memory address */
+ WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg->pCLUT);
+
+ /* Write background CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM),
+ ((CLUTCfg->Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg->CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos)));
+
+ /* Enable the CLUT Transfer Complete, transfer Error, configuration Error and CLUT Access Error interrupts */
+ __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE |DMA2D_IT_CAE);
+
+ /* Enable the CLUT loading for the background */
+ SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START);
+ }
+ /* Configure the CLUT of the foreground DMA2D layer */
+ else
+ {
+ /* Write foreground CLUT memory address */
+ WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg->pCLUT);
+
+ /* Write foreground CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM),
+ ((CLUTCfg->Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg->CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos)));
+
+ /* Enable the CLUT Transfer Complete, transfer Error, configuration Error and CLUT Access Error interrupts */
+ __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE |DMA2D_IT_CAE);
+
+ /* Enable the CLUT loading for the foreground */
+ SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start DMA2D CLUT Loading.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains
+ * the configuration information for the color look up table.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @note API obsolete and maintained for compatibility with legacy. User is
+ * invited to resort to HAL_DMA2D_CLUTStartLoad() instead to benefit from
+ * code compactness, code size and improved heap usage.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_CLUTLoad(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef CLUTCfg, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LAYER(LayerIdx));
+ assert_param(IS_DMA2D_CLUT_CM(CLUTCfg.CLUTColorMode));
+ assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg.Size));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Configure the CLUT of the background DMA2D layer */
+ if(LayerIdx == DMA2D_BACKGROUND_LAYER)
+ {
+ /* Write background CLUT memory address */
+ WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg.pCLUT);
+
+ /* Write background CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM),
+ ((CLUTCfg.Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos)));
+
+ /* Enable the CLUT loading for the background */
+ SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START);
+ }
+ /* Configure the CLUT of the foreground DMA2D layer */
+ else
+ {
+ /* Write foreground CLUT memory address */
+ WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg.pCLUT);
+
+ /* Write foreground CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM),
+ ((CLUTCfg.Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos)));
+
+ /* Enable the CLUT loading for the foreground */
+ SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start DMA2D CLUT Loading with interrupt enabled.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains
+ * the configuration information for the color look up table.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @note API obsolete and maintained for compatibility with legacy. User is
+ * invited to resort to HAL_DMA2D_CLUTStartLoad_IT() instead to benefit
+ * from code compactness, code size and improved heap usage.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_CLUTLoad_IT(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef CLUTCfg, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LAYER(LayerIdx));
+ assert_param(IS_DMA2D_CLUT_CM(CLUTCfg.CLUTColorMode));
+ assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg.Size));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Configure the CLUT of the background DMA2D layer */
+ if(LayerIdx == DMA2D_BACKGROUND_LAYER)
+ {
+ /* Write background CLUT memory address */
+ WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg.pCLUT);
+
+ /* Write background CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM),
+ ((CLUTCfg.Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos)));
+
+ /* Enable the CLUT Transfer Complete, transfer Error, configuration Error and CLUT Access Error interrupts */
+ __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE |DMA2D_IT_CAE);
+
+ /* Enable the CLUT loading for the background */
+ SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START);
+ }
+ /* Configure the CLUT of the foreground DMA2D layer */
+ else
+ {
+ /* Write foreground CLUT memory address */
+ WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg.pCLUT);
+
+ /* Write foreground CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM),
+ ((CLUTCfg.Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos)));
+
+ /* Enable the CLUT Transfer Complete, transfer Error, configuration Error and CLUT Access Error interrupts */
+ __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE |DMA2D_IT_CAE);
+
+ /* Enable the CLUT loading for the foreground */
+ SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort the DMA2D CLUT loading.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_CLUTLoading_Abort(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx)
+{
+ uint32_t tickstart;
+ const __IO uint32_t * reg = &(hdma2d->Instance->BGPFCCR); /* by default, point at background register */
+
+ /* Abort the CLUT loading */
+ SET_BIT(hdma2d->Instance->CR, DMA2D_CR_ABORT);
+
+ /* If foreground CLUT loading is considered, update local variables */
+ if(LayerIdx == DMA2D_FOREGROUND_LAYER)
+ {
+ reg = &(hdma2d->Instance->FGPFCCR);
+ }
+
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check if the CLUT loading is aborted */
+ while((*reg & DMA2D_BGPFCCR_START) != 0U)
+ {
+ if((HAL_GetTick() - tickstart ) > DMA2D_TIMEOUT_ABORT)
+ {
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT;
+
+ /* Change the DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Disable the CLUT Transfer Complete, Transfer Error, Configuration Error and CLUT Access Error interrupts */
+ __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE |DMA2D_IT_CAE);
+
+ /* Change the DMA2D state*/
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Suspend the DMA2D CLUT loading.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_CLUTLoading_Suspend(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx)
+{
+ uint32_t tickstart;
+ uint32_t loadsuspended;
+ const __IO uint32_t * reg = &(hdma2d->Instance->BGPFCCR); /* by default, point at background register */
+
+ /* Suspend the CLUT loading */
+ SET_BIT(hdma2d->Instance->CR, DMA2D_CR_SUSP);
+
+ /* If foreground CLUT loading is considered, update local variables */
+ if(LayerIdx == DMA2D_FOREGROUND_LAYER)
+ {
+ reg = &(hdma2d->Instance->FGPFCCR);
+ }
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check if the CLUT loading is suspended */
+ loadsuspended = ((hdma2d->Instance->CR & DMA2D_CR_SUSP) == DMA2D_CR_SUSP)? 1UL: 0UL; /*1st condition: Suspend Check*/
+ loadsuspended |= ((*reg & DMA2D_BGPFCCR_START) != DMA2D_BGPFCCR_START)? 1UL: 0UL; /*2nd condition: Not Start Check */
+ while (loadsuspended == 0UL)
+ {
+ if((HAL_GetTick() - tickstart ) > DMA2D_TIMEOUT_SUSPEND)
+ {
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT;
+
+ /* Change the DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ loadsuspended = ((hdma2d->Instance->CR & DMA2D_CR_SUSP) == DMA2D_CR_SUSP)? 1UL: 0UL; /*1st condition: Suspend Check*/
+ loadsuspended |= ((*reg & DMA2D_BGPFCCR_START) != DMA2D_BGPFCCR_START)? 1UL: 0UL; /*2nd condition: Not Start Check */
+ }
+
+ /* Check whether or not a transfer is actually suspended and change the DMA2D state accordingly */
+ if ((*reg & DMA2D_BGPFCCR_START) != 0U)
+ {
+ hdma2d->State = HAL_DMA2D_STATE_SUSPEND;
+ }
+ else
+ {
+ /* Make sure SUSP bit is cleared since it is meaningless
+ when no tranfer is on-going */
+ CLEAR_BIT(hdma2d->Instance->CR, DMA2D_CR_SUSP);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the DMA2D CLUT loading.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_CLUTLoading_Resume(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx)
+{
+ /* Check the SUSP and START bits for background or foreground CLUT loading */
+ if(LayerIdx == DMA2D_BACKGROUND_LAYER)
+ {
+ /* Background CLUT loading suspension check */
+ if ((hdma2d->Instance->CR & DMA2D_CR_SUSP) == DMA2D_CR_SUSP)
+ {
+ if((hdma2d->Instance->BGPFCCR & DMA2D_BGPFCCR_START) == DMA2D_BGPFCCR_START)
+ {
+ /* Ongoing CLUT loading is suspended: change the DMA2D state before resuming */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+ }
+ }
+ }
+ else
+ {
+ /* Foreground CLUT loading suspension check */
+ if ((hdma2d->Instance->CR & DMA2D_CR_SUSP) == DMA2D_CR_SUSP)
+ {
+ if ((hdma2d->Instance->FGPFCCR & DMA2D_FGPFCCR_START) == DMA2D_FGPFCCR_START)
+ {
+ /* Ongoing CLUT loading is suspended: change the DMA2D state before resuming */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+ }
+ }
+ }
+
+ /* Resume the CLUT loading */
+ CLEAR_BIT(hdma2d->Instance->CR, DMA2D_CR_SUSP);
+
+ return HAL_OK;
+}
+
+
+/**
+
+ * @brief Polling for transfer complete or CLUT loading.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_PollForTransfer(DMA2D_HandleTypeDef *hdma2d, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t layer_start;
+ __IO uint32_t isrflags = 0x0U;
+
+ /* Polling for DMA2D transfer */
+ if((hdma2d->Instance->CR & DMA2D_CR_START) != 0U)
+ {
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while(__HAL_DMA2D_GET_FLAG(hdma2d, DMA2D_FLAG_TC) == 0U)
+ {
+ isrflags = READ_REG(hdma2d->Instance->ISR);
+ if ((isrflags & (DMA2D_FLAG_CE|DMA2D_FLAG_TE)) != 0U)
+ {
+ if ((isrflags & DMA2D_FLAG_CE) != 0U)
+ {
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CE;
+ }
+ if ((isrflags & DMA2D_FLAG_TE) != 0U)
+ {
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TE;
+ }
+ /* Clear the transfer and configuration error flags */
+ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CE | DMA2D_FLAG_TE);
+
+ /* Change DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_ERROR;
+ }
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U))
+ {
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT;
+
+ /* Change the DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_TIMEOUT;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ /* Polling for CLUT loading (foreground or background) */
+ layer_start = hdma2d->Instance->FGPFCCR & DMA2D_FGPFCCR_START;
+ layer_start |= hdma2d->Instance->BGPFCCR & DMA2D_BGPFCCR_START;
+ if (layer_start != 0U)
+ {
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while(__HAL_DMA2D_GET_FLAG(hdma2d, DMA2D_FLAG_CTC) == 0U)
+ {
+ isrflags = READ_REG(hdma2d->Instance->ISR);
+ if ((isrflags & (DMA2D_FLAG_CAE|DMA2D_FLAG_CE|DMA2D_FLAG_TE)) != 0U)
+ {
+ if ((isrflags & DMA2D_FLAG_CAE) != 0U)
+ {
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CAE;
+ }
+ if ((isrflags & DMA2D_FLAG_CE) != 0U)
+ {
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CE;
+ }
+ if ((isrflags & DMA2D_FLAG_TE) != 0U)
+ {
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TE;
+ }
+ /* Clear the CLUT Access Error, Configuration Error and Transfer Error flags */
+ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CAE | DMA2D_FLAG_CE | DMA2D_FLAG_TE);
+
+ /* Change DMA2D state */
+ hdma2d->State= HAL_DMA2D_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_ERROR;
+ }
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U))
+ {
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT;
+
+ /* Change the DMA2D state */
+ hdma2d->State= HAL_DMA2D_STATE_TIMEOUT;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Clear the transfer complete and CLUT loading flags */
+ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_TC|DMA2D_FLAG_CTC);
+
+ /* Change DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+}
+/**
+ * @brief Handle DMA2D interrupt request.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval HAL status
+ */
+void HAL_DMA2D_IRQHandler(DMA2D_HandleTypeDef *hdma2d)
+{
+ uint32_t isrflags = READ_REG(hdma2d->Instance->ISR);
+ uint32_t crflags = READ_REG(hdma2d->Instance->CR);
+
+ /* Transfer Error Interrupt management ***************************************/
+ if ((isrflags & DMA2D_FLAG_TE) != 0U)
+ {
+ if ((crflags & DMA2D_IT_TE) != 0U)
+ {
+ /* Disable the transfer Error interrupt */
+ __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_TE);
+
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TE;
+
+ /* Clear the transfer error flag */
+ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_TE);
+
+ /* Change DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ if(hdma2d->XferErrorCallback != NULL)
+ {
+ /* Transfer error Callback */
+ hdma2d->XferErrorCallback(hdma2d);
+ }
+ }
+ }
+ /* Configuration Error Interrupt management **********************************/
+ if ((isrflags & DMA2D_FLAG_CE) != 0U)
+ {
+ if ((crflags & DMA2D_IT_CE) != 0U)
+ {
+ /* Disable the Configuration Error interrupt */
+ __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_CE);
+
+ /* Clear the Configuration error flag */
+ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CE);
+
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CE;
+
+ /* Change DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ if(hdma2d->XferErrorCallback != NULL)
+ {
+ /* Transfer error Callback */
+ hdma2d->XferErrorCallback(hdma2d);
+ }
+ }
+ }
+ /* CLUT access Error Interrupt management ***********************************/
+ if ((isrflags & DMA2D_FLAG_CAE) != 0U)
+ {
+ if ((crflags & DMA2D_IT_CAE) != 0U)
+ {
+ /* Disable the CLUT access error interrupt */
+ __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_CAE);
+
+ /* Clear the CLUT access error flag */
+ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CAE);
+
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CAE;
+
+ /* Change DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ if(hdma2d->XferErrorCallback != NULL)
+ {
+ /* Transfer error Callback */
+ hdma2d->XferErrorCallback(hdma2d);
+ }
+ }
+ }
+ /* Transfer watermark Interrupt management **********************************/
+ if ((isrflags & DMA2D_FLAG_TW) != 0U)
+ {
+ if ((crflags & DMA2D_IT_TW) != 0U)
+ {
+ /* Disable the transfer watermark interrupt */
+ __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_TW);
+
+ /* Clear the transfer watermark flag */
+ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_TW);
+
+ /* Transfer watermark Callback */
+#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1)
+ hdma2d->LineEventCallback(hdma2d);
+#else
+ HAL_DMA2D_LineEventCallback(hdma2d);
+#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */
+
+ }
+ }
+ /* Transfer Complete Interrupt management ************************************/
+ if ((isrflags & DMA2D_FLAG_TC) != 0U)
+ {
+ if ((crflags & DMA2D_IT_TC) != 0U)
+ {
+ /* Disable the transfer complete interrupt */
+ __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_TC);
+
+ /* Clear the transfer complete flag */
+ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_TC);
+
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_NONE;
+
+ /* Change DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ if(hdma2d->XferCpltCallback != NULL)
+ {
+ /* Transfer complete Callback */
+ hdma2d->XferCpltCallback(hdma2d);
+ }
+ }
+ }
+ /* CLUT Transfer Complete Interrupt management ******************************/
+ if ((isrflags & DMA2D_FLAG_CTC) != 0U)
+ {
+ if ((crflags & DMA2D_IT_CTC) != 0U)
+ {
+ /* Disable the CLUT transfer complete interrupt */
+ __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_CTC);
+
+ /* Clear the CLUT transfer complete flag */
+ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CTC);
+
+ /* Update error code */
+ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_NONE;
+
+ /* Change DMA2D state */
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ /* CLUT Transfer complete Callback */
+#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1)
+ hdma2d->CLUTLoadingCpltCallback(hdma2d);
+#else
+ HAL_DMA2D_CLUTLoadingCpltCallback(hdma2d);
+#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */
+ }
+ }
+
+}
+
+/**
+ * @brief Transfer watermark callback.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval None
+ */
+__weak void HAL_DMA2D_LineEventCallback(DMA2D_HandleTypeDef *hdma2d)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdma2d);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ the HAL_DMA2D_LineEventCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief CLUT Transfer Complete callback.
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval None
+ */
+__weak void HAL_DMA2D_CLUTLoadingCpltCallback(DMA2D_HandleTypeDef *hdma2d)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdma2d);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ the HAL_DMA2D_CLUTLoadingCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DMA2D_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure the DMA2D foreground or background layer parameters.
+ (+) Configure the DMA2D CLUT transfer.
+ (+) Configure the line watermark
+ (+) Configure the dead time value.
+ (+) Enable or disable the dead time value functionality.
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the DMA2D Layer according to the specified
+ * parameters in the DMA2D_HandleTypeDef.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_ConfigLayer(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx)
+{
+ DMA2D_LayerCfgTypeDef *pLayerCfg;
+ uint32_t regMask, regValue;
+
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LAYER(LayerIdx));
+ assert_param(IS_DMA2D_OFFSET(hdma2d->LayerCfg[LayerIdx].InputOffset));
+ if(hdma2d->Init.Mode != DMA2D_R2M)
+ {
+ assert_param(IS_DMA2D_INPUT_COLOR_MODE(hdma2d->LayerCfg[LayerIdx].InputColorMode));
+ if(hdma2d->Init.Mode != DMA2D_M2M)
+ {
+ assert_param(IS_DMA2D_ALPHA_MODE(hdma2d->LayerCfg[LayerIdx].AlphaMode));
+ }
+ }
+ assert_param(IS_DMA2D_ALPHA_INVERTED(hdma2d->LayerCfg[LayerIdx].AlphaInverted));
+ assert_param(IS_DMA2D_RB_SWAP(hdma2d->LayerCfg[LayerIdx].RedBlueSwap));
+
+ if((LayerIdx == DMA2D_FOREGROUND_LAYER) && (hdma2d->LayerCfg[LayerIdx].InputColorMode == DMA2D_INPUT_YCBCR))
+ {
+ assert_param(IS_DMA2D_CHROMA_SUB_SAMPLING(hdma2d->LayerCfg[LayerIdx].ChromaSubSampling));
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ pLayerCfg = &hdma2d->LayerCfg[LayerIdx];
+
+ /* Prepare the value to be written to the BGPFCCR or FGPFCCR register */
+ regValue = pLayerCfg->InputColorMode | (pLayerCfg->AlphaMode << DMA2D_BGPFCCR_AM_Pos) |\
+ (pLayerCfg->AlphaInverted << DMA2D_BGPFCCR_AI_Pos) | (pLayerCfg->RedBlueSwap << DMA2D_BGPFCCR_RBS_Pos);
+ regMask = (DMA2D_BGPFCCR_CM | DMA2D_BGPFCCR_AM | DMA2D_BGPFCCR_ALPHA | DMA2D_BGPFCCR_AI | DMA2D_BGPFCCR_RBS);
+
+
+ if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))
+ {
+ regValue |= (pLayerCfg->InputAlpha & DMA2D_BGPFCCR_ALPHA);
+ }
+ else
+ {
+ regValue |= (pLayerCfg->InputAlpha << DMA2D_BGPFCCR_ALPHA_Pos);
+ }
+
+ /* Configure the background DMA2D layer */
+ if(LayerIdx == DMA2D_BACKGROUND_LAYER)
+ {
+ /* Write DMA2D BGPFCCR register */
+ MODIFY_REG(hdma2d->Instance->BGPFCCR, regMask, regValue);
+
+ /* DMA2D BGOR register configuration -------------------------------------*/
+ WRITE_REG(hdma2d->Instance->BGOR, pLayerCfg->InputOffset);
+
+ /* DMA2D BGCOLR register configuration -------------------------------------*/
+ if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))
+ {
+ WRITE_REG(hdma2d->Instance->BGCOLR, pLayerCfg->InputAlpha & (DMA2D_BGCOLR_BLUE|DMA2D_BGCOLR_GREEN|DMA2D_BGCOLR_RED));
+ }
+ }
+ /* Configure the foreground DMA2D layer */
+ else
+ {
+
+ if(pLayerCfg->InputColorMode == DMA2D_INPUT_YCBCR)
+ {
+ regValue |= (pLayerCfg->ChromaSubSampling << DMA2D_FGPFCCR_CSS_Pos);
+ regMask |= DMA2D_FGPFCCR_CSS;
+ }
+
+ /* Write DMA2D FGPFCCR register */
+ MODIFY_REG(hdma2d->Instance->FGPFCCR, regMask, regValue);
+
+ /* DMA2D FGOR register configuration -------------------------------------*/
+ WRITE_REG(hdma2d->Instance->FGOR, pLayerCfg->InputOffset);
+
+ /* DMA2D FGCOLR register configuration -------------------------------------*/
+ if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))
+ {
+ WRITE_REG(hdma2d->Instance->FGCOLR, pLayerCfg->InputAlpha & (DMA2D_FGCOLR_BLUE|DMA2D_FGCOLR_GREEN|DMA2D_FGCOLR_RED));
+ }
+ }
+ /* Initialize the DMA2D state*/
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the DMA2D CLUT Transfer.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains
+ * the configuration information for the color look up table.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
+ * @note API obsolete and maintained for compatibility with legacy. User is invited
+ * to resort to HAL_DMA2D_CLUTStartLoad() instead to benefit from code compactness,
+ * code size and improved heap usage.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_ConfigCLUT(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef CLUTCfg, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LAYER(LayerIdx));
+ assert_param(IS_DMA2D_CLUT_CM(CLUTCfg.CLUTColorMode));
+ assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg.Size));
+
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Configure the CLUT of the background DMA2D layer */
+ if(LayerIdx == DMA2D_BACKGROUND_LAYER)
+ {
+ /* Write background CLUT memory address */
+ WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg.pCLUT);
+
+ /* Write background CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM),
+ ((CLUTCfg.Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos)));
+ }
+ /* Configure the CLUT of the foreground DMA2D layer */
+ else
+ {
+ /* Write foreground CLUT memory address */
+ WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg.pCLUT);
+
+ /* Write foreground CLUT size and CLUT color mode */
+ MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM),
+ ((CLUTCfg.Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos)));
+ }
+
+ /* Set the DMA2D state to Ready*/
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Configure the line watermark.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @param Line Line Watermark configuration (maximum 16-bit long value expected).
+ * @note HAL_DMA2D_ProgramLineEvent() API enables the transfer watermark interrupt.
+ * @note The transfer watermark interrupt is disabled once it has occurred.
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_DMA2D_ProgramLineEvent(DMA2D_HandleTypeDef *hdma2d, uint32_t Line)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA2D_LINEWATERMARK(Line));
+
+ if (Line > DMA2D_LWR_LW)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Process locked */
+ __HAL_LOCK(hdma2d);
+
+ /* Change DMA2D peripheral state */
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Sets the Line watermark configuration */
+ WRITE_REG(hdma2d->Instance->LWR, Line);
+
+ /* Enable the Line interrupt */
+ __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TW);
+
+ /* Initialize the DMA2D state*/
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Enable DMA2D dead time feature.
+ * @param hdma2d DMA2D handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_EnableDeadTime(DMA2D_HandleTypeDef *hdma2d)
+{
+ /* Process Locked */
+ __HAL_LOCK(hdma2d);
+
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Set DMA2D_AMTCR EN bit */
+ SET_BIT(hdma2d->Instance->AMTCR, DMA2D_AMTCR_EN);
+
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable DMA2D dead time feature.
+ * @param hdma2d DMA2D handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_DisableDeadTime(DMA2D_HandleTypeDef *hdma2d)
+{
+ /* Process Locked */
+ __HAL_LOCK(hdma2d);
+
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Clear DMA2D_AMTCR EN bit */
+ CLEAR_BIT(hdma2d->Instance->AMTCR, DMA2D_AMTCR_EN);
+
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure dead time.
+ * @note The dead time value represents the guaranteed minimum number of cycles between
+ * two consecutive transactions on the AHB bus.
+ * @param hdma2d DMA2D handle.
+ * @param DeadTime dead time value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA2D_ConfigDeadTime(DMA2D_HandleTypeDef *hdma2d, uint8_t DeadTime)
+{
+ /* Process Locked */
+ __HAL_LOCK(hdma2d);
+
+ hdma2d->State = HAL_DMA2D_STATE_BUSY;
+
+ /* Set DMA2D_AMTCR DT field */
+ MODIFY_REG(hdma2d->Instance->AMTCR, DMA2D_AMTCR_DT, (((uint32_t) DeadTime) << DMA2D_AMTCR_DT_Pos));
+
+ hdma2d->State = HAL_DMA2D_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma2d);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+
+/** @defgroup DMA2D_Exported_Functions_Group4 Peripheral State and Error functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to:
+ (+) Get the DMA2D state
+ (+) Get the DMA2D error code
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the DMA2D state
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the DMA2D.
+ * @retval HAL state
+ */
+HAL_DMA2D_StateTypeDef HAL_DMA2D_GetState(DMA2D_HandleTypeDef *hdma2d)
+{
+ return hdma2d->State;
+}
+
+/**
+ * @brief Return the DMA2D error code
+ * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for DMA2D.
+ * @retval DMA2D Error Code
+ */
+uint32_t HAL_DMA2D_GetError(DMA2D_HandleTypeDef *hdma2d)
+{
+ return hdma2d->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup DMA2D_Private_Functions DMA2D Private Functions
+ * @{
+ */
+
+/**
+ * @brief Set the DMA2D transfer parameters.
+ * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA2D.
+ * @param pdata The source memory Buffer address
+ * @param DstAddress The destination memory Buffer address
+ * @param Width The width of data to be transferred from source to destination.
+ * @param Height The height of data to be transferred from source to destination.
+ * @retval HAL status
+ */
+static void DMA2D_SetConfig(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, uint32_t Height)
+{
+ uint32_t tmp;
+ uint32_t tmp1;
+ uint32_t tmp2;
+ uint32_t tmp3;
+ uint32_t tmp4;
+
+ /* Configure DMA2D data size */
+ MODIFY_REG(hdma2d->Instance->NLR, (DMA2D_NLR_NL|DMA2D_NLR_PL), (Height| (Width << DMA2D_NLR_PL_Pos)));
+
+ /* Configure DMA2D destination address */
+ WRITE_REG(hdma2d->Instance->OMAR, DstAddress);
+
+ /* Register to memory DMA2D mode selected */
+ if (hdma2d->Init.Mode == DMA2D_R2M)
+ {
+ tmp1 = pdata & DMA2D_OCOLR_ALPHA_1;
+ tmp2 = pdata & DMA2D_OCOLR_RED_1;
+ tmp3 = pdata & DMA2D_OCOLR_GREEN_1;
+ tmp4 = pdata & DMA2D_OCOLR_BLUE_1;
+
+ /* Prepare the value to be written to the OCOLR register according to the color mode */
+ if (hdma2d->Init.ColorMode == DMA2D_OUTPUT_ARGB8888)
+ {
+ tmp = (tmp3 | tmp2 | tmp1| tmp4);
+ }
+ else if (hdma2d->Init.ColorMode == DMA2D_OUTPUT_RGB888)
+ {
+ tmp = (tmp3 | tmp2 | tmp4);
+ }
+ else if (hdma2d->Init.ColorMode == DMA2D_OUTPUT_RGB565)
+ {
+ tmp2 = (tmp2 >> 19U);
+ tmp3 = (tmp3 >> 10U);
+ tmp4 = (tmp4 >> 3U );
+ tmp = ((tmp3 << 5U) | (tmp2 << 11U) | tmp4);
+ }
+ else if (hdma2d->Init.ColorMode == DMA2D_OUTPUT_ARGB1555)
+ {
+ tmp1 = (tmp1 >> 31U);
+ tmp2 = (tmp2 >> 19U);
+ tmp3 = (tmp3 >> 11U);
+ tmp4 = (tmp4 >> 3U );
+ tmp = ((tmp3 << 5U) | (tmp2 << 10U) | (tmp1 << 15U) | tmp4);
+ }
+ else /* Dhdma2d->Init.ColorMode = DMA2D_OUTPUT_ARGB4444 */
+ {
+ tmp1 = (tmp1 >> 28U);
+ tmp2 = (tmp2 >> 20U);
+ tmp3 = (tmp3 >> 12U);
+ tmp4 = (tmp4 >> 4U );
+ tmp = ((tmp3 << 4U) | (tmp2 << 8U) | (tmp1 << 12U) | tmp4);
+ }
+ /* Write to DMA2D OCOLR register */
+ WRITE_REG(hdma2d->Instance->OCOLR, tmp);
+ }
+ else if(hdma2d->Init.Mode == DMA2D_M2M_BLEND_FG) /*M2M_blending with fixed color FG DMA2D Mode selected*/
+ {
+ WRITE_REG(hdma2d->Instance->BGMAR , pdata);
+ }
+ else /* M2M, M2M_PFC,M2M_Blending or M2M_blending with fixed color BG DMA2D Mode */
+ {
+ /* Configure DMA2D source address */
+ WRITE_REG(hdma2d->Instance->FGMAR, pdata);
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+#endif /* DMA2D */
+#endif /* HAL_DMA2D_MODULE_ENABLED */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dma_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dma_ex.c
new file mode 100644
index 0000000000..6a48d942d4
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dma_ex.c
@@ -0,0 +1,714 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c
new file mode 100644
index 0000000000..badc634835
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dsi.c
@@ -0,0 +1,2705 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dsi.c
+ * @author MCD Application Team
+ * @brief DSI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the DSI peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Errors functions
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Use @ref HAL_DSI_Init() function to initialize the DSI Host IP and program the required
+ PLL parameters, number of lanes and TX Escape clock divider.
+ (#) Use @ref HAL_DSI_ConfigAdaptedCommandMode() function to configure the DSI host in adapted
+ command mode.
+ (#) When operating in video mode , use @ref HAL_DSI_ConfigVideoMode() to configure the DSI host.
+ (#) Function @ref HAL_DSI_ConfigCommand() is used to configure the DSI commands behavior in low power mode.
+ (#) To configure the DSI PHY timings parameters, use function @ref HAL_DSI_ConfigPhyTimer().
+ (#) The DSI Host can be started/stopped using respectively functions @ref HAL_DSI_Start() and @ref HAL_DSI_Stop().
+ Functions @ref HAL_DSI_ShortWrite(), @ref HAL_DSI_LongWrite() and @ref HAL_DSI_Read() allows respectively
+ to write DSI short packets, long packets and to read DSI packets.
+
+ (#) The DSI Host Offers two Low power modes :
+ (+) Low Power Mode on data lanes only: Only DSI data lanes are shut down.
+ It is possible to enter/exit from this mode using respectively functions @ref HAL_DSI_EnterULPMData()
+ and @ref HAL_DSI_ExitULPMData()
+
+ (+) Low Power Mode on data and clock lanes : All DSI lanes are shut down including data and clock lanes.
+ It is possible to enter/exit from this mode using respectively functions @ref HAL_DSI_EnterULPM()
+ and @ref HAL_DSI_ExitULPM()
+
+ (#) User can select the DSI errors to be reported/monitored using function @ref HAL_DSI_ConfigErrorMonitor()
+ When an error occurs, the callback @ref HAL_DSI_ErrorCallback() is asserted and then user can retrieve
+ the error code by calling function @ref HAL_DSI_GetError()
+
+ (#) To control DSI state you can use the following function: HAL_DSI_GetState()
+
+ *** DSI HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in DSI HAL driver.
+
+ (+) __HAL_DSI_ENABLE: Enable the DSI Host.
+ (+) __HAL_DSI_DISABLE: Disable the DSI Host.
+ (+) __HAL_DSI_WRAPPER_ENABLE: Enables the DSI wrapper.
+ (+) __HAL_DSI_WRAPPER_DISABLE: Disable the DSI wrapper.
+ (+) __HAL_DSI_PLL_ENABLE: Enables the DSI PLL.
+ (+) __HAL_DSI_PLL_DISABLE: Disables the DSI PLL.
+ (+) __HAL_DSI_REG_ENABLE: Enables the DSI regulator.
+ (+) __HAL_DSI_REG_DISABLE: Disables the DSI regulator.
+ (+) __HAL_DSI_GET_FLAG: Get the DSI pending flags.
+ (+) __HAL_DSI_CLEAR_FLAG: Clears the DSI pending flags.
+ (+) __HAL_DSI_ENABLE_IT: Enables the specified DSI interrupts.
+ (+) __HAL_DSI_DISABLE_IT: Disables the specified DSI interrupts.
+ (+) __HAL_DSI_GET_IT_SOURCE: Checks whether the specified DSI interrupt source is enabled or not.
+
+
+
+ *** Callback registration ***
+ =============================================
+
+ The compilation define USE_HAL_DSI_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Function @ref HAL_DSI_RegisterCallback() to register a callback.
+
+ Function @ref HAL_DSI_RegisterCallback() allows to register following callbacks:
+ (+) TearingEffectCallback : DSI Tearing Effect Callback.
+ (+) EndOfRefreshCallback : DSI End Of Refresh Callback.
+ (+) ErrorCallback : DSI Error Callback
+ (+) MspInitCallback : DSI MspInit.
+ (+) MspDeInitCallback : DSI MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function @ref HAL_DSI_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ @ref HAL_DSI_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TearingEffectCallback : DSI Tearing Effect Callback.
+ (+) EndOfRefreshCallback : DSI End Of Refresh Callback.
+ (+) ErrorCallback : DSI Error Callback
+ (+) MspInitCallback : DSI MspInit.
+ (+) MspDeInitCallback : DSI MspDeInit.
+
+ By default, after the HAL_DSI_Init and when the state is HAL_DSI_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples @ref HAL_DSI_TearingEffectCallback(), @ref HAL_DSI_EndOfRefreshCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak function in the HAL_DSI_Init/ @ref HAL_DSI_DeInit only when
+ these callbacks are null (not registered beforehand).
+ if not, MspInit or MspDeInit are not null, the @ref HAL_DSI_Init/ @ref HAL_DSI_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in HAL_DSI_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_DSI_STATE_READY or HAL_DSI_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 @ref HAL_DSI_RegisterCallback() before calling @ref HAL_DSI_DeInit
+ or HAL_DSI_Init function.
+
+ When The compilation define USE_HAL_DSI_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 DSI HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_DSI_MODULE_ENABLED
+
+#if defined(DSI)
+
+/** @addtogroup DSI
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @addtogroup DSI_Private_Constants
+ * @{
+ */
+#define DSI_TIMEOUT_VALUE ((uint32_t)1000U) /* 1s */
+
+#define DSI_ERROR_ACK_MASK (DSI_ISR0_AE0 | DSI_ISR0_AE1 | DSI_ISR0_AE2 | DSI_ISR0_AE3 | \
+ DSI_ISR0_AE4 | DSI_ISR0_AE5 | DSI_ISR0_AE6 | DSI_ISR0_AE7 | \
+ DSI_ISR0_AE8 | DSI_ISR0_AE9 | DSI_ISR0_AE10 | DSI_ISR0_AE11 | \
+ DSI_ISR0_AE12 | DSI_ISR0_AE13 | DSI_ISR0_AE14 | DSI_ISR0_AE15)
+#define DSI_ERROR_PHY_MASK (DSI_ISR0_PE0 | DSI_ISR0_PE1 | DSI_ISR0_PE2 | DSI_ISR0_PE3 | DSI_ISR0_PE4)
+#define DSI_ERROR_TX_MASK DSI_ISR1_TOHSTX
+#define DSI_ERROR_RX_MASK DSI_ISR1_TOLPRX
+#define DSI_ERROR_ECC_MASK (DSI_ISR1_ECCSE | DSI_ISR1_ECCME)
+#define DSI_ERROR_CRC_MASK DSI_ISR1_CRCE
+#define DSI_ERROR_PSE_MASK DSI_ISR1_PSE
+#define DSI_ERROR_EOT_MASK DSI_ISR1_EOTPE
+#define DSI_ERROR_OVF_MASK DSI_ISR1_LPWRE
+#define DSI_ERROR_GEN_MASK (DSI_ISR1_GCWRE | DSI_ISR1_GPWRE | DSI_ISR1_GPTXE | DSI_ISR1_GPRDE | DSI_ISR1_GPRXE)
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void DSI_ConfigPacketHeader(DSI_TypeDef *DSIx, uint32_t ChannelID, uint32_t DataType, uint32_t Data0,
+ uint32_t Data1);
+
+static HAL_StatusTypeDef DSI_ShortWrite(DSI_HandleTypeDef *hdsi,
+ uint32_t ChannelID,
+ uint32_t Mode,
+ uint32_t Param1,
+ uint32_t Param2);
+
+/* Private functions ---------------------------------------------------------*/
+/**
+ * @brief Generic DSI packet header configuration
+ * @param DSIx Pointer to DSI register base
+ * @param ChannelID Virtual channel ID of the header packet
+ * @param DataType Packet data type of the header packet
+ * This parameter can be any value of :
+ * @arg DSI_SHORT_WRITE_PKT_Data_Type
+ * @arg DSI_LONG_WRITE_PKT_Data_Type
+ * @arg DSI_SHORT_READ_PKT_Data_Type
+ * @arg DSI_MAX_RETURN_PKT_SIZE
+ * @param Data0 Word count LSB
+ * @param Data1 Word count MSB
+ * @retval None
+ */
+static void DSI_ConfigPacketHeader(DSI_TypeDef *DSIx,
+ uint32_t ChannelID,
+ uint32_t DataType,
+ uint32_t Data0,
+ uint32_t Data1)
+{
+ /* Update the DSI packet header with new information */
+ DSIx->GHCR = (DataType | (ChannelID << 6U) | (Data0 << 8U) | (Data1 << 16U));
+}
+
+/**
+ * @brief write short DCS or short Generic command
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param ChannelID Virtual channel ID.
+ * @param Mode DSI short packet data type.
+ * This parameter can be any value of @arg DSI_SHORT_WRITE_PKT_Data_Type.
+ * @param Param1 DSC command or first generic parameter.
+ * This parameter can be any value of @arg DSI_DCS_Command or a
+ * generic command code.
+ * @param Param2 DSC parameter or second generic parameter.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef DSI_ShortWrite(DSI_HandleTypeDef *hdsi,
+ uint32_t ChannelID,
+ uint32_t Mode,
+ uint32_t Param1,
+ uint32_t Param2)
+{
+ uint32_t tickstart;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait for Command FIFO Empty */
+ while((hdsi->Instance->GPSR & DSI_GPSR_CMDFE) == 0U)
+ {
+ /* Check for the Timeout */
+ if((HAL_GetTick() - tickstart ) > DSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Configure the packet to send a short DCS command with 0 or 1 parameter */
+ /* Update the DSI packet header with new information */
+ hdsi->Instance->GHCR = (Mode | (ChannelID << 6U) | (Param1 << 8U) | (Param2 << 16U));
+
+ return HAL_OK;
+}
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup DSI_Exported_Functions
+ * @{
+ */
+
+/** @defgroup DSI_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the DSI
+ (+) De-initialize the DSI
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the DSI according to the specified
+ * parameters in the DSI_InitTypeDef and create the associated handle.
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param PLLInit pointer to a DSI_PLLInitTypeDef structure that contains
+ * the PLL Clock structure definition for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_Init(DSI_HandleTypeDef *hdsi, DSI_PLLInitTypeDef *PLLInit)
+{
+ uint32_t tickstart;
+ uint32_t unitIntervalx4;
+ uint32_t tempIDF;
+
+ /* Check the DSI handle allocation */
+ if (hdsi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check function parameters */
+ assert_param(IS_DSI_PLL_NDIV(PLLInit->PLLNDIV));
+ assert_param(IS_DSI_PLL_IDF(PLLInit->PLLIDF));
+ assert_param(IS_DSI_PLL_ODF(PLLInit->PLLODF));
+ assert_param(IS_DSI_AUTO_CLKLANE_CONTROL(hdsi->Init.AutomaticClockLaneControl));
+ assert_param(IS_DSI_NUMBER_OF_LANES(hdsi->Init.NumberOfLanes));
+
+#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1)
+ if (hdsi->State == HAL_DSI_STATE_RESET)
+ {
+ /* Reset the DSI callback to the legacy weak callbacks */
+ hdsi->TearingEffectCallback = HAL_DSI_TearingEffectCallback; /* Legacy weak TearingEffectCallback */
+ hdsi->EndOfRefreshCallback = HAL_DSI_EndOfRefreshCallback; /* Legacy weak EndOfRefreshCallback */
+ hdsi->ErrorCallback = HAL_DSI_ErrorCallback; /* Legacy weak ErrorCallback */
+
+ if (hdsi->MspInitCallback == NULL)
+ {
+ hdsi->MspInitCallback = HAL_DSI_MspInit;
+ }
+ /* Initialize the low level hardware */
+ hdsi->MspInitCallback(hdsi);
+ }
+#else
+ if (hdsi->State == HAL_DSI_STATE_RESET)
+ {
+ /* Initialize the low level hardware */
+ HAL_DSI_MspInit(hdsi);
+ }
+#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */
+
+ /* Change DSI peripheral state */
+ hdsi->State = HAL_DSI_STATE_BUSY;
+
+ /**************** Turn on the regulator and enable the DSI PLL ****************/
+
+ /* Enable the regulator */
+ __HAL_DSI_REG_ENABLE(hdsi);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until the regulator is ready */
+ while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_RRS) == 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set the PLL division factors */
+ hdsi->Instance->WRPCR &= ~(DSI_WRPCR_PLL_NDIV | DSI_WRPCR_PLL_IDF | DSI_WRPCR_PLL_ODF);
+ hdsi->Instance->WRPCR |= (((PLLInit->PLLNDIV) << 2U) | ((PLLInit->PLLIDF) << 11U) | ((PLLInit->PLLODF) << 16U));
+
+ /* Enable the DSI PLL */
+ __HAL_DSI_PLL_ENABLE(hdsi);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait for the lock of the PLL */
+ while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /*************************** Set the PHY parameters ***************************/
+
+ /* D-PHY clock and digital enable*/
+ hdsi->Instance->PCTLR |= (DSI_PCTLR_CKE | DSI_PCTLR_DEN);
+
+ /* Clock lane configuration */
+ hdsi->Instance->CLCR &= ~(DSI_CLCR_DPCC | DSI_CLCR_ACR);
+ hdsi->Instance->CLCR |= (DSI_CLCR_DPCC | hdsi->Init.AutomaticClockLaneControl);
+
+ /* Configure the number of active data lanes */
+ hdsi->Instance->PCONFR &= ~DSI_PCONFR_NL;
+ hdsi->Instance->PCONFR |= hdsi->Init.NumberOfLanes;
+
+ /************************ Set the DSI clock parameters ************************/
+
+ /* Set the TX escape clock division factor */
+ hdsi->Instance->CCR &= ~DSI_CCR_TXECKDIV;
+ hdsi->Instance->CCR |= hdsi->Init.TXEscapeCkdiv;
+
+ /* Calculate the bit period in high-speed mode in unit of 0.25 ns (UIX4) */
+ /* The equation is : UIX4 = IntegerPart( (1000/F_PHY_Mhz) * 4 ) */
+ /* Where : F_PHY_Mhz = (NDIV * HSE_Mhz) / (IDF * ODF) */
+ tempIDF = (PLLInit->PLLIDF > 0U) ? PLLInit->PLLIDF : 1U;
+ unitIntervalx4 = (4000000U * tempIDF * ((1UL << (0x3U & PLLInit->PLLODF)))) / ((HSE_VALUE / 1000U) * PLLInit->PLLNDIV);
+
+ /* Set the bit period in high-speed mode */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_UIX4;
+ hdsi->Instance->WPCR[0U] |= unitIntervalx4;
+
+ /****************************** Error management *****************************/
+
+ /* Disable all error interrupts and reset the Error Mask */
+ hdsi->Instance->IER[0U] = 0U;
+ hdsi->Instance->IER[1U] = 0U;
+ hdsi->ErrorMsk = 0U;
+
+ /* Initialise the error code */
+ hdsi->ErrorCode = HAL_DSI_ERROR_NONE;
+
+ /* Initialize the DSI state*/
+ hdsi->State = HAL_DSI_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief De-initializes the DSI peripheral registers to their default reset
+ * values.
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_DeInit(DSI_HandleTypeDef *hdsi)
+{
+ /* Check the DSI handle allocation */
+ if (hdsi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Change DSI peripheral state */
+ hdsi->State = HAL_DSI_STATE_BUSY;
+
+ /* Disable the DSI wrapper */
+ __HAL_DSI_WRAPPER_DISABLE(hdsi);
+
+ /* Disable the DSI host */
+ __HAL_DSI_DISABLE(hdsi);
+
+ /* D-PHY clock and digital disable */
+ hdsi->Instance->PCTLR &= ~(DSI_PCTLR_CKE | DSI_PCTLR_DEN);
+
+ /* Turn off the DSI PLL */
+ __HAL_DSI_PLL_DISABLE(hdsi);
+
+ /* Disable the regulator */
+ __HAL_DSI_REG_DISABLE(hdsi);
+
+#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1)
+ if (hdsi->MspDeInitCallback == NULL)
+ {
+ hdsi->MspDeInitCallback = HAL_DSI_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ hdsi->MspDeInitCallback(hdsi);
+#else
+ /* DeInit the low level hardware */
+ HAL_DSI_MspDeInit(hdsi);
+#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */
+
+ /* Initialise the error code */
+ hdsi->ErrorCode = HAL_DSI_ERROR_NONE;
+
+ /* Initialize the DSI state*/
+ hdsi->State = HAL_DSI_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the error monitor flags
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param ActiveErrors indicates which error interrupts will be enabled.
+ * This parameter can be any combination of @arg DSI_Error_Data_Type.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ConfigErrorMonitor(DSI_HandleTypeDef *hdsi, uint32_t ActiveErrors)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ hdsi->Instance->IER[0U] = 0U;
+ hdsi->Instance->IER[1U] = 0U;
+
+ /* Store active errors to the handle */
+ hdsi->ErrorMsk = ActiveErrors;
+
+ if ((ActiveErrors & HAL_DSI_ERROR_ACK) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[0U] |= DSI_ERROR_ACK_MASK;
+ }
+
+ if ((ActiveErrors & HAL_DSI_ERROR_PHY) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[0U] |= DSI_ERROR_PHY_MASK;
+ }
+
+ if ((ActiveErrors & HAL_DSI_ERROR_TX) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[1U] |= DSI_ERROR_TX_MASK;
+ }
+
+ if ((ActiveErrors & HAL_DSI_ERROR_RX) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[1U] |= DSI_ERROR_RX_MASK;
+ }
+
+ if ((ActiveErrors & HAL_DSI_ERROR_ECC) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[1U] |= DSI_ERROR_ECC_MASK;
+ }
+
+ if ((ActiveErrors & HAL_DSI_ERROR_CRC) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[1U] |= DSI_ERROR_CRC_MASK;
+ }
+
+ if ((ActiveErrors & HAL_DSI_ERROR_PSE) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[1U] |= DSI_ERROR_PSE_MASK;
+ }
+
+ if ((ActiveErrors & HAL_DSI_ERROR_EOT) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[1U] |= DSI_ERROR_EOT_MASK;
+ }
+
+ if ((ActiveErrors & HAL_DSI_ERROR_OVF) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[1U] |= DSI_ERROR_OVF_MASK;
+ }
+
+ if ((ActiveErrors & HAL_DSI_ERROR_GEN) != 0U)
+ {
+ /* Enable the interrupt generation on selected errors */
+ hdsi->Instance->IER[1U] |= DSI_ERROR_GEN_MASK;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the DSI MSP.
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval None
+ */
+__weak void HAL_DSI_MspInit(DSI_HandleTypeDef *hdsi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdsi);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DSI_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief De-initializes the DSI MSP.
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval None
+ */
+__weak void HAL_DSI_MspDeInit(DSI_HandleTypeDef *hdsi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdsi);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DSI_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User DSI Callback
+ * To be used instead of the weak predefined callback
+ * @param hdsi dsi handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg HAL_DSI_TEARING_EFFECT_CB_ID Tearing Effect Callback ID
+ * @arg HAL_DSI_ENDOF_REFRESH_CB_ID End Of Refresh Callback ID
+ * @arg HAL_DSI_ERROR_CB_ID Error Callback ID
+ * @arg HAL_DSI_MSPINIT_CB_ID MspInit callback ID
+ * @arg HAL_DSI_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_DSI_RegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_CallbackIDTypeDef CallbackID,
+ pDSI_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ if (hdsi->State == HAL_DSI_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DSI_TEARING_EFFECT_CB_ID :
+ hdsi->TearingEffectCallback = pCallback;
+ break;
+
+ case HAL_DSI_ENDOF_REFRESH_CB_ID :
+ hdsi->EndOfRefreshCallback = pCallback;
+ break;
+
+ case HAL_DSI_ERROR_CB_ID :
+ hdsi->ErrorCallback = pCallback;
+ break;
+
+ case HAL_DSI_MSPINIT_CB_ID :
+ hdsi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_DSI_MSPDEINIT_CB_ID :
+ hdsi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hdsi->State == HAL_DSI_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DSI_MSPINIT_CB_ID :
+ hdsi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_DSI_MSPDEINIT_CB_ID :
+ hdsi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdsi);
+
+ return status;
+}
+
+/**
+ * @brief Unregister a DSI Callback
+ * DSI callabck is redirected to the weak predefined callback
+ * @param hdsi dsi handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg HAL_DSI_TEARING_EFFECT_CB_ID Tearing Effect Callback ID
+ * @arg HAL_DSI_ENDOF_REFRESH_CB_ID End Of Refresh Callback ID
+ * @arg HAL_DSI_ERROR_CB_ID Error Callback ID
+ * @arg HAL_DSI_MSPINIT_CB_ID MspInit callback ID
+ * @arg HAL_DSI_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_DSI_UnRegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ if (hdsi->State == HAL_DSI_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DSI_TEARING_EFFECT_CB_ID :
+ hdsi->TearingEffectCallback = HAL_DSI_TearingEffectCallback; /* Legacy weak TearingEffectCallback */
+ break;
+
+ case HAL_DSI_ENDOF_REFRESH_CB_ID :
+ hdsi->EndOfRefreshCallback = HAL_DSI_EndOfRefreshCallback; /* Legacy weak EndOfRefreshCallback */
+ break;
+
+ case HAL_DSI_ERROR_CB_ID :
+ hdsi->ErrorCallback = HAL_DSI_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_DSI_MSPINIT_CB_ID :
+ hdsi->MspInitCallback = HAL_DSI_MspInit; /* Legcay weak MspInit Callback */
+ break;
+
+ case HAL_DSI_MSPDEINIT_CB_ID :
+ hdsi->MspDeInitCallback = HAL_DSI_MspDeInit; /* Legcay weak MspDeInit Callback */
+ break;
+
+ default :
+ /* Update the error code */
+ hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hdsi->State == HAL_DSI_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DSI_MSPINIT_CB_ID :
+ hdsi->MspInitCallback = HAL_DSI_MspInit; /* Legcay weak MspInit Callback */
+ break;
+
+ case HAL_DSI_MSPDEINIT_CB_ID :
+ hdsi->MspDeInitCallback = HAL_DSI_MspDeInit; /* Legcay weak MspDeInit Callback */
+ break;
+
+ default :
+ /* Update the error code */
+ hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdsi);
+
+ return status;
+}
+#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup DSI_Group2 IO operation functions
+ * @brief IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides function allowing to:
+ (+) Handle DSI interrupt request
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Handles DSI interrupt request.
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+void HAL_DSI_IRQHandler(DSI_HandleTypeDef *hdsi)
+{
+ uint32_t ErrorStatus0, ErrorStatus1;
+
+ /* Tearing Effect Interrupt management ***************************************/
+ if (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_TE) != 0U)
+ {
+ if (__HAL_DSI_GET_IT_SOURCE(hdsi, DSI_IT_TE) != 0U)
+ {
+ /* Clear the Tearing Effect Interrupt Flag */
+ __HAL_DSI_CLEAR_FLAG(hdsi, DSI_FLAG_TE);
+
+ /* Tearing Effect Callback */
+#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1)
+ /*Call registered Tearing Effect callback */
+ hdsi->TearingEffectCallback(hdsi);
+#else
+ /*Call legacy Tearing Effect callback*/
+ HAL_DSI_TearingEffectCallback(hdsi);
+#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* End of Refresh Interrupt management ***************************************/
+ if (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_ER) != 0U)
+ {
+ if (__HAL_DSI_GET_IT_SOURCE(hdsi, DSI_IT_ER) != 0U)
+ {
+ /* Clear the End of Refresh Interrupt Flag */
+ __HAL_DSI_CLEAR_FLAG(hdsi, DSI_FLAG_ER);
+
+ /* End of Refresh Callback */
+#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1)
+ /*Call registered End of refresh callback */
+ hdsi->EndOfRefreshCallback(hdsi);
+#else
+ /*Call Legacy End of refresh callback */
+ HAL_DSI_EndOfRefreshCallback(hdsi);
+#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Error Interrupts management ***********************************************/
+ if (hdsi->ErrorMsk != 0U)
+ {
+ ErrorStatus0 = hdsi->Instance->ISR[0U];
+ ErrorStatus0 &= hdsi->Instance->IER[0U];
+ ErrorStatus1 = hdsi->Instance->ISR[1U];
+ ErrorStatus1 &= hdsi->Instance->IER[1U];
+
+ if ((ErrorStatus0 & DSI_ERROR_ACK_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_ACK;
+ }
+
+ if ((ErrorStatus0 & DSI_ERROR_PHY_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_PHY;
+ }
+
+ if ((ErrorStatus1 & DSI_ERROR_TX_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_TX;
+ }
+
+ if ((ErrorStatus1 & DSI_ERROR_RX_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_RX;
+ }
+
+ if ((ErrorStatus1 & DSI_ERROR_ECC_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_ECC;
+ }
+
+ if ((ErrorStatus1 & DSI_ERROR_CRC_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_CRC;
+ }
+
+ if ((ErrorStatus1 & DSI_ERROR_PSE_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_PSE;
+ }
+
+ if ((ErrorStatus1 & DSI_ERROR_EOT_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_EOT;
+ }
+
+ if ((ErrorStatus1 & DSI_ERROR_OVF_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_OVF;
+ }
+
+ if ((ErrorStatus1 & DSI_ERROR_GEN_MASK) != 0U)
+ {
+ hdsi->ErrorCode |= HAL_DSI_ERROR_GEN;
+ }
+
+ /* Check only selected errors */
+ if (hdsi->ErrorCode != HAL_DSI_ERROR_NONE)
+ {
+ /* DSI error interrupt callback */
+#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1)
+ /*Call registered Error callback */
+ hdsi->ErrorCallback(hdsi);
+#else
+ /*Call Legacy Error callback */
+ HAL_DSI_ErrorCallback(hdsi);
+#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @brief Tearing Effect DSI callback.
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval None
+ */
+__weak void HAL_DSI_TearingEffectCallback(DSI_HandleTypeDef *hdsi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdsi);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DSI_TearingEffectCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief End of Refresh DSI callback.
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval None
+ */
+__weak void HAL_DSI_EndOfRefreshCallback(DSI_HandleTypeDef *hdsi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdsi);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DSI_EndOfRefreshCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Operation Error DSI callback.
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval None
+ */
+__weak void HAL_DSI_ErrorCallback(DSI_HandleTypeDef *hdsi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdsi);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DSI_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DSI_Group3 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure the Generic interface read-back Virtual Channel ID
+ (+) Select video mode and configure the corresponding parameters
+ (+) Configure command transmission mode: High-speed or Low-power
+ (+) Configure the flow control
+ (+) Configure the DSI PHY timer
+ (+) Configure the DSI HOST timeout
+ (+) Configure the DSI HOST timeout
+ (+) Start/Stop the DSI module
+ (+) Refresh the display in command mode
+ (+) Controls the display color mode in Video mode
+ (+) Control the display shutdown in Video mode
+ (+) write short DCS or short Generic command
+ (+) write long DCS or long Generic command
+ (+) Read command (DCS or generic)
+ (+) Enter/Exit the Ultra Low Power Mode on data only (D-PHY PLL running)
+ (+) Enter/Exit the Ultra Low Power Mode on data only and clock (D-PHY PLL turned off)
+ (+) Start/Stop test pattern generation
+ (+) Slew-Rate And Delay Tuning
+ (+) Low-Power Reception Filter Tuning
+ (+) Activate an additional current path on all lanes to meet the SDDTx parameter
+ (+) Custom lane pins configuration
+ (+) Set custom timing for the PHY
+ (+) Force the Clock/Data Lane in TX Stop Mode
+ (+) Force LP Receiver in Low-Power Mode
+ (+) Force Data Lanes in RX Mode after a BTA
+ (+) Enable a pull-down on the lanes to prevent from floating states when unused
+ (+) Switch off the contention detection on data lanes
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the Generic interface read-back Virtual Channel ID.
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param VirtualChannelID Virtual channel ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_SetGenericVCID(DSI_HandleTypeDef *hdsi, uint32_t VirtualChannelID)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Update the GVCID register */
+ hdsi->Instance->GVCIDR &= ~DSI_GVCIDR_VCID;
+ hdsi->Instance->GVCIDR |= VirtualChannelID;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Select video mode and configure the corresponding parameters
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param VidCfg pointer to a DSI_VidCfgTypeDef structure that contains
+ * the DSI video mode configuration parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ConfigVideoMode(DSI_HandleTypeDef *hdsi, DSI_VidCfgTypeDef *VidCfg)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check the parameters */
+ assert_param(IS_DSI_COLOR_CODING(VidCfg->ColorCoding));
+ assert_param(IS_DSI_VIDEO_MODE_TYPE(VidCfg->Mode));
+ assert_param(IS_DSI_LP_COMMAND(VidCfg->LPCommandEnable));
+ assert_param(IS_DSI_LP_HFP(VidCfg->LPHorizontalFrontPorchEnable));
+ assert_param(IS_DSI_LP_HBP(VidCfg->LPHorizontalBackPorchEnable));
+ assert_param(IS_DSI_LP_VACTIVE(VidCfg->LPVerticalActiveEnable));
+ assert_param(IS_DSI_LP_VFP(VidCfg->LPVerticalFrontPorchEnable));
+ assert_param(IS_DSI_LP_VBP(VidCfg->LPVerticalBackPorchEnable));
+ assert_param(IS_DSI_LP_VSYNC(VidCfg->LPVerticalSyncActiveEnable));
+ assert_param(IS_DSI_FBTAA(VidCfg->FrameBTAAcknowledgeEnable));
+ assert_param(IS_DSI_DE_POLARITY(VidCfg->DEPolarity));
+ assert_param(IS_DSI_VSYNC_POLARITY(VidCfg->VSPolarity));
+ assert_param(IS_DSI_HSYNC_POLARITY(VidCfg->HSPolarity));
+ /* Check the LooselyPacked variant only in 18-bit mode */
+ if (VidCfg->ColorCoding == DSI_RGB666)
+ {
+ assert_param(IS_DSI_LOOSELY_PACKED(VidCfg->LooselyPacked));
+ }
+
+ /* Select video mode by resetting CMDM and DSIM bits */
+ hdsi->Instance->MCR &= ~DSI_MCR_CMDM;
+ hdsi->Instance->WCFGR &= ~DSI_WCFGR_DSIM;
+
+ /* Configure the video mode transmission type */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_VMT;
+ hdsi->Instance->VMCR |= VidCfg->Mode;
+
+ /* Configure the video packet size */
+ hdsi->Instance->VPCR &= ~DSI_VPCR_VPSIZE;
+ hdsi->Instance->VPCR |= VidCfg->PacketSize;
+
+ /* Set the chunks number to be transmitted through the DSI link */
+ hdsi->Instance->VCCR &= ~DSI_VCCR_NUMC;
+ hdsi->Instance->VCCR |= VidCfg->NumberOfChunks;
+
+ /* Set the size of the null packet */
+ hdsi->Instance->VNPCR &= ~DSI_VNPCR_NPSIZE;
+ hdsi->Instance->VNPCR |= VidCfg->NullPacketSize;
+
+ /* Select the virtual channel for the LTDC interface traffic */
+ hdsi->Instance->LVCIDR &= ~DSI_LVCIDR_VCID;
+ hdsi->Instance->LVCIDR |= VidCfg->VirtualChannelID;
+
+ /* Configure the polarity of control signals */
+ hdsi->Instance->LPCR &= ~(DSI_LPCR_DEP | DSI_LPCR_VSP | DSI_LPCR_HSP);
+ hdsi->Instance->LPCR |= (VidCfg->DEPolarity | VidCfg->VSPolarity | VidCfg->HSPolarity);
+
+ /* Select the color coding for the host */
+ hdsi->Instance->LCOLCR &= ~DSI_LCOLCR_COLC;
+ hdsi->Instance->LCOLCR |= VidCfg->ColorCoding;
+
+ /* Select the color coding for the wrapper */
+ hdsi->Instance->WCFGR &= ~DSI_WCFGR_COLMUX;
+ hdsi->Instance->WCFGR |= ((VidCfg->ColorCoding) << 1U);
+
+ /* Enable/disable the loosely packed variant to 18-bit configuration */
+ if (VidCfg->ColorCoding == DSI_RGB666)
+ {
+ hdsi->Instance->LCOLCR &= ~DSI_LCOLCR_LPE;
+ hdsi->Instance->LCOLCR |= VidCfg->LooselyPacked;
+ }
+
+ /* Set the Horizontal Synchronization Active (HSA) in lane byte clock cycles */
+ hdsi->Instance->VHSACR &= ~DSI_VHSACR_HSA;
+ hdsi->Instance->VHSACR |= VidCfg->HorizontalSyncActive;
+
+ /* Set the Horizontal Back Porch (HBP) in lane byte clock cycles */
+ hdsi->Instance->VHBPCR &= ~DSI_VHBPCR_HBP;
+ hdsi->Instance->VHBPCR |= VidCfg->HorizontalBackPorch;
+
+ /* Set the total line time (HLINE=HSA+HBP+HACT+HFP) in lane byte clock cycles */
+ hdsi->Instance->VLCR &= ~DSI_VLCR_HLINE;
+ hdsi->Instance->VLCR |= VidCfg->HorizontalLine;
+
+ /* Set the Vertical Synchronization Active (VSA) */
+ hdsi->Instance->VVSACR &= ~DSI_VVSACR_VSA;
+ hdsi->Instance->VVSACR |= VidCfg->VerticalSyncActive;
+
+ /* Set the Vertical Back Porch (VBP)*/
+ hdsi->Instance->VVBPCR &= ~DSI_VVBPCR_VBP;
+ hdsi->Instance->VVBPCR |= VidCfg->VerticalBackPorch;
+
+ /* Set the Vertical Front Porch (VFP)*/
+ hdsi->Instance->VVFPCR &= ~DSI_VVFPCR_VFP;
+ hdsi->Instance->VVFPCR |= VidCfg->VerticalFrontPorch;
+
+ /* Set the Vertical Active period*/
+ hdsi->Instance->VVACR &= ~DSI_VVACR_VA;
+ hdsi->Instance->VVACR |= VidCfg->VerticalActive;
+
+ /* Configure the command transmission mode */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_LPCE;
+ hdsi->Instance->VMCR |= VidCfg->LPCommandEnable;
+
+ /* Low power largest packet size */
+ hdsi->Instance->LPMCR &= ~DSI_LPMCR_LPSIZE;
+ hdsi->Instance->LPMCR |= ((VidCfg->LPLargestPacketSize) << 16U);
+
+ /* Low power VACT largest packet size */
+ hdsi->Instance->LPMCR &= ~DSI_LPMCR_VLPSIZE;
+ hdsi->Instance->LPMCR |= VidCfg->LPVACTLargestPacketSize;
+
+ /* Enable LP transition in HFP period */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_LPHFPE;
+ hdsi->Instance->VMCR |= VidCfg->LPHorizontalFrontPorchEnable;
+
+ /* Enable LP transition in HBP period */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_LPHBPE;
+ hdsi->Instance->VMCR |= VidCfg->LPHorizontalBackPorchEnable;
+
+ /* Enable LP transition in VACT period */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_LPVAE;
+ hdsi->Instance->VMCR |= VidCfg->LPVerticalActiveEnable;
+
+ /* Enable LP transition in VFP period */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_LPVFPE;
+ hdsi->Instance->VMCR |= VidCfg->LPVerticalFrontPorchEnable;
+
+ /* Enable LP transition in VBP period */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_LPVBPE;
+ hdsi->Instance->VMCR |= VidCfg->LPVerticalBackPorchEnable;
+
+ /* Enable LP transition in vertical sync period */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_LPVSAE;
+ hdsi->Instance->VMCR |= VidCfg->LPVerticalSyncActiveEnable;
+
+ /* Enable the request for an acknowledge response at the end of a frame */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_FBTAAE;
+ hdsi->Instance->VMCR |= VidCfg->FrameBTAAcknowledgeEnable;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Select adapted command mode and configure the corresponding parameters
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param CmdCfg pointer to a DSI_CmdCfgTypeDef structure that contains
+ * the DSI command mode configuration parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ConfigAdaptedCommandMode(DSI_HandleTypeDef *hdsi, DSI_CmdCfgTypeDef *CmdCfg)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check the parameters */
+ assert_param(IS_DSI_COLOR_CODING(CmdCfg->ColorCoding));
+ assert_param(IS_DSI_TE_SOURCE(CmdCfg->TearingEffectSource));
+ assert_param(IS_DSI_TE_POLARITY(CmdCfg->TearingEffectPolarity));
+ assert_param(IS_DSI_AUTOMATIC_REFRESH(CmdCfg->AutomaticRefresh));
+ assert_param(IS_DSI_VS_POLARITY(CmdCfg->VSyncPol));
+ assert_param(IS_DSI_TE_ACK_REQUEST(CmdCfg->TEAcknowledgeRequest));
+ assert_param(IS_DSI_DE_POLARITY(CmdCfg->DEPolarity));
+ assert_param(IS_DSI_VSYNC_POLARITY(CmdCfg->VSPolarity));
+ assert_param(IS_DSI_HSYNC_POLARITY(CmdCfg->HSPolarity));
+
+ /* Select command mode by setting CMDM and DSIM bits */
+ hdsi->Instance->MCR |= DSI_MCR_CMDM;
+ hdsi->Instance->WCFGR &= ~DSI_WCFGR_DSIM;
+ hdsi->Instance->WCFGR |= DSI_WCFGR_DSIM;
+
+ /* Select the virtual channel for the LTDC interface traffic */
+ hdsi->Instance->LVCIDR &= ~DSI_LVCIDR_VCID;
+ hdsi->Instance->LVCIDR |= CmdCfg->VirtualChannelID;
+
+ /* Configure the polarity of control signals */
+ hdsi->Instance->LPCR &= ~(DSI_LPCR_DEP | DSI_LPCR_VSP | DSI_LPCR_HSP);
+ hdsi->Instance->LPCR |= (CmdCfg->DEPolarity | CmdCfg->VSPolarity | CmdCfg->HSPolarity);
+
+ /* Select the color coding for the host */
+ hdsi->Instance->LCOLCR &= ~DSI_LCOLCR_COLC;
+ hdsi->Instance->LCOLCR |= CmdCfg->ColorCoding;
+
+ /* Select the color coding for the wrapper */
+ hdsi->Instance->WCFGR &= ~DSI_WCFGR_COLMUX;
+ hdsi->Instance->WCFGR |= ((CmdCfg->ColorCoding) << 1U);
+
+ /* Configure the maximum allowed size for write memory command */
+ hdsi->Instance->LCCR &= ~DSI_LCCR_CMDSIZE;
+ hdsi->Instance->LCCR |= CmdCfg->CommandSize;
+
+ /* Configure the tearing effect source and polarity and select the refresh mode */
+ hdsi->Instance->WCFGR &= ~(DSI_WCFGR_TESRC | DSI_WCFGR_TEPOL | DSI_WCFGR_AR | DSI_WCFGR_VSPOL);
+ hdsi->Instance->WCFGR |= (CmdCfg->TearingEffectSource | CmdCfg->TearingEffectPolarity | CmdCfg->AutomaticRefresh |
+ CmdCfg->VSyncPol);
+
+ /* Configure the tearing effect acknowledge request */
+ hdsi->Instance->CMCR &= ~DSI_CMCR_TEARE;
+ hdsi->Instance->CMCR |= CmdCfg->TEAcknowledgeRequest;
+
+ /* Enable the Tearing Effect interrupt */
+ __HAL_DSI_ENABLE_IT(hdsi, DSI_IT_TE);
+
+ /* Enable the End of Refresh interrupt */
+ __HAL_DSI_ENABLE_IT(hdsi, DSI_IT_ER);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure command transmission mode: High-speed or Low-power
+ * and enable/disable acknowledge request after packet transmission
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param LPCmd pointer to a DSI_LPCmdTypeDef structure that contains
+ * the DSI command transmission mode configuration parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ConfigCommand(DSI_HandleTypeDef *hdsi, DSI_LPCmdTypeDef *LPCmd)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ assert_param(IS_DSI_LP_GSW0P(LPCmd->LPGenShortWriteNoP));
+ assert_param(IS_DSI_LP_GSW1P(LPCmd->LPGenShortWriteOneP));
+ assert_param(IS_DSI_LP_GSW2P(LPCmd->LPGenShortWriteTwoP));
+ assert_param(IS_DSI_LP_GSR0P(LPCmd->LPGenShortReadNoP));
+ assert_param(IS_DSI_LP_GSR1P(LPCmd->LPGenShortReadOneP));
+ assert_param(IS_DSI_LP_GSR2P(LPCmd->LPGenShortReadTwoP));
+ assert_param(IS_DSI_LP_GLW(LPCmd->LPGenLongWrite));
+ assert_param(IS_DSI_LP_DSW0P(LPCmd->LPDcsShortWriteNoP));
+ assert_param(IS_DSI_LP_DSW1P(LPCmd->LPDcsShortWriteOneP));
+ assert_param(IS_DSI_LP_DSR0P(LPCmd->LPDcsShortReadNoP));
+ assert_param(IS_DSI_LP_DLW(LPCmd->LPDcsLongWrite));
+ assert_param(IS_DSI_LP_MRDP(LPCmd->LPMaxReadPacket));
+ assert_param(IS_DSI_ACK_REQUEST(LPCmd->AcknowledgeRequest));
+
+ /* Select High-speed or Low-power for command transmission */
+ hdsi->Instance->CMCR &= ~(DSI_CMCR_GSW0TX | \
+ DSI_CMCR_GSW1TX | \
+ DSI_CMCR_GSW2TX | \
+ DSI_CMCR_GSR0TX | \
+ DSI_CMCR_GSR1TX | \
+ DSI_CMCR_GSR2TX | \
+ DSI_CMCR_GLWTX | \
+ DSI_CMCR_DSW0TX | \
+ DSI_CMCR_DSW1TX | \
+ DSI_CMCR_DSR0TX | \
+ DSI_CMCR_DLWTX | \
+ DSI_CMCR_MRDPS);
+ hdsi->Instance->CMCR |= (LPCmd->LPGenShortWriteNoP | \
+ LPCmd->LPGenShortWriteOneP | \
+ LPCmd->LPGenShortWriteTwoP | \
+ LPCmd->LPGenShortReadNoP | \
+ LPCmd->LPGenShortReadOneP | \
+ LPCmd->LPGenShortReadTwoP | \
+ LPCmd->LPGenLongWrite | \
+ LPCmd->LPDcsShortWriteNoP | \
+ LPCmd->LPDcsShortWriteOneP | \
+ LPCmd->LPDcsShortReadNoP | \
+ LPCmd->LPDcsLongWrite | \
+ LPCmd->LPMaxReadPacket);
+
+ /* Configure the acknowledge request after each packet transmission */
+ hdsi->Instance->CMCR &= ~DSI_CMCR_ARE;
+ hdsi->Instance->CMCR |= LPCmd->AcknowledgeRequest;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the flow control parameters
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param FlowControl flow control feature(s) to be enabled.
+ * This parameter can be any combination of @arg DSI_FlowControl.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ConfigFlowControl(DSI_HandleTypeDef *hdsi, uint32_t FlowControl)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check the parameters */
+ assert_param(IS_DSI_FLOW_CONTROL(FlowControl));
+
+ /* Set the DSI Host Protocol Configuration Register */
+ hdsi->Instance->PCR &= ~DSI_FLOW_CONTROL_ALL;
+ hdsi->Instance->PCR |= FlowControl;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the DSI PHY timer parameters
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param PhyTimers DSI_PHY_TimerTypeDef structure that contains
+ * the DSI PHY timing parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ConfigPhyTimer(DSI_HandleTypeDef *hdsi, DSI_PHY_TimerTypeDef *PhyTimers)
+{
+ uint32_t maxTime;
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ maxTime = (PhyTimers->ClockLaneLP2HSTime > PhyTimers->ClockLaneHS2LPTime) ? PhyTimers->ClockLaneLP2HSTime :
+ PhyTimers->ClockLaneHS2LPTime;
+
+ /* Clock lane timer configuration */
+
+ /* In Automatic Clock Lane control mode, the DSI Host can turn off the clock lane between two
+ High-Speed transmission.
+ To do so, the DSI Host calculates the time required for the clock lane to change from HighSpeed
+ to Low-Power and from Low-Power to High-Speed.
+ This timings are configured by the HS2LP_TIME and LP2HS_TIME in the DSI Host Clock Lane Timer Configuration Register (DSI_CLTCR).
+ But the DSI Host is not calculating LP2HS_TIME + HS2LP_TIME but 2 x HS2LP_TIME.
+
+ Workaround : Configure HS2LP_TIME and LP2HS_TIME with the same value being the max of HS2LP_TIME or LP2HS_TIME.
+ */
+ hdsi->Instance->CLTCR &= ~(DSI_CLTCR_LP2HS_TIME | DSI_CLTCR_HS2LP_TIME);
+ hdsi->Instance->CLTCR |= (maxTime | ((maxTime) << 16U));
+
+ /* Data lane timer configuration */
+ hdsi->Instance->DLTCR &= ~(DSI_DLTCR_MRD_TIME | DSI_DLTCR_LP2HS_TIME | DSI_DLTCR_HS2LP_TIME);
+ hdsi->Instance->DLTCR |= (PhyTimers->DataLaneMaxReadTime | ((PhyTimers->DataLaneLP2HSTime) << 16U) | ((
+ PhyTimers->DataLaneHS2LPTime) << 24U));
+
+ /* Configure the wait period to request HS transmission after a stop state */
+ hdsi->Instance->PCONFR &= ~DSI_PCONFR_SW_TIME;
+ hdsi->Instance->PCONFR |= ((PhyTimers->StopWaitTime) << 8U);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the DSI HOST timeout parameters
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param HostTimeouts DSI_HOST_TimeoutTypeDef structure that contains
+ * the DSI host timeout parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ConfigHostTimeouts(DSI_HandleTypeDef *hdsi, DSI_HOST_TimeoutTypeDef *HostTimeouts)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Set the timeout clock division factor */
+ hdsi->Instance->CCR &= ~DSI_CCR_TOCKDIV;
+ hdsi->Instance->CCR |= ((HostTimeouts->TimeoutCkdiv) << 8U);
+
+ /* High-speed transmission timeout */
+ hdsi->Instance->TCCR[0U] &= ~DSI_TCCR0_HSTX_TOCNT;
+ hdsi->Instance->TCCR[0U] |= ((HostTimeouts->HighSpeedTransmissionTimeout) << 16U);
+
+ /* Low-power reception timeout */
+ hdsi->Instance->TCCR[0U] &= ~DSI_TCCR0_LPRX_TOCNT;
+ hdsi->Instance->TCCR[0U] |= HostTimeouts->LowPowerReceptionTimeout;
+
+ /* High-speed read timeout */
+ hdsi->Instance->TCCR[1U] &= ~DSI_TCCR1_HSRD_TOCNT;
+ hdsi->Instance->TCCR[1U] |= HostTimeouts->HighSpeedReadTimeout;
+
+ /* Low-power read timeout */
+ hdsi->Instance->TCCR[2U] &= ~DSI_TCCR2_LPRD_TOCNT;
+ hdsi->Instance->TCCR[2U] |= HostTimeouts->LowPowerReadTimeout;
+
+ /* High-speed write timeout */
+ hdsi->Instance->TCCR[3U] &= ~DSI_TCCR3_HSWR_TOCNT;
+ hdsi->Instance->TCCR[3U] |= HostTimeouts->HighSpeedWriteTimeout;
+
+ /* High-speed write presp mode */
+ hdsi->Instance->TCCR[3U] &= ~DSI_TCCR3_PM;
+ hdsi->Instance->TCCR[3U] |= HostTimeouts->HighSpeedWritePrespMode;
+
+ /* Low-speed write timeout */
+ hdsi->Instance->TCCR[4U] &= ~DSI_TCCR4_LPWR_TOCNT;
+ hdsi->Instance->TCCR[4U] |= HostTimeouts->LowPowerWriteTimeout;
+
+ /* BTA timeout */
+ hdsi->Instance->TCCR[5U] &= ~DSI_TCCR5_BTA_TOCNT;
+ hdsi->Instance->TCCR[5U] |= HostTimeouts->BTATimeout;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the DSI module
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_Start(DSI_HandleTypeDef *hdsi)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Enable the DSI host */
+ __HAL_DSI_ENABLE(hdsi);
+
+ /* Enable the DSI wrapper */
+ __HAL_DSI_WRAPPER_ENABLE(hdsi);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the DSI module
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_Stop(DSI_HandleTypeDef *hdsi)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Disable the DSI host */
+ __HAL_DSI_DISABLE(hdsi);
+
+ /* Disable the DSI wrapper */
+ __HAL_DSI_WRAPPER_DISABLE(hdsi);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Refresh the display in command mode
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_Refresh(DSI_HandleTypeDef *hdsi)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Update the display */
+ hdsi->Instance->WCR |= DSI_WCR_LTDCEN;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Controls the display color mode in Video mode
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param ColorMode Color mode (full or 8-colors).
+ * This parameter can be any value of @arg DSI_Color_Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ColorMode(DSI_HandleTypeDef *hdsi, uint32_t ColorMode)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check the parameters */
+ assert_param(IS_DSI_COLOR_MODE(ColorMode));
+
+ /* Update the display color mode */
+ hdsi->Instance->WCR &= ~DSI_WCR_COLM;
+ hdsi->Instance->WCR |= ColorMode;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Control the display shutdown in Video mode
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param Shutdown Shut-down (Display-ON or Display-OFF).
+ * This parameter can be any value of @arg DSI_ShutDown
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_Shutdown(DSI_HandleTypeDef *hdsi, uint32_t Shutdown)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check the parameters */
+ assert_param(IS_DSI_SHUT_DOWN(Shutdown));
+
+ /* Update the display Shutdown */
+ hdsi->Instance->WCR &= ~DSI_WCR_SHTDN;
+ hdsi->Instance->WCR |= Shutdown;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief write short DCS or short Generic command
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param ChannelID Virtual channel ID.
+ * @param Mode DSI short packet data type.
+ * This parameter can be any value of @arg DSI_SHORT_WRITE_PKT_Data_Type.
+ * @param Param1 DSC command or first generic parameter.
+ * This parameter can be any value of @arg DSI_DCS_Command or a
+ * generic command code.
+ * @param Param2 DSC parameter or second generic parameter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ShortWrite(DSI_HandleTypeDef *hdsi,
+ uint32_t ChannelID,
+ uint32_t Mode,
+ uint32_t Param1,
+ uint32_t Param2)
+{
+ HAL_StatusTypeDef status;
+ /* Check the parameters */
+ assert_param(IS_DSI_SHORT_WRITE_PACKET_TYPE(Mode));
+
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ status = DSI_ShortWrite(hdsi, ChannelID, Mode, Param1, Param2);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return status;
+}
+
+/**
+ * @brief write long DCS or long Generic command
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param ChannelID Virtual channel ID.
+ * @param Mode DSI long packet data type.
+ * This parameter can be any value of @arg DSI_LONG_WRITE_PKT_Data_Type.
+ * @param NbParams Number of parameters.
+ * @param Param1 DSC command or first generic parameter.
+ * This parameter can be any value of @arg DSI_DCS_Command or a
+ * generic command code
+ * @param ParametersTable Pointer to parameter values table.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_LongWrite(DSI_HandleTypeDef *hdsi,
+ uint32_t ChannelID,
+ uint32_t Mode,
+ uint32_t NbParams,
+ uint32_t Param1,
+ uint8_t *ParametersTable)
+{
+ uint32_t uicounter, nbBytes, count;
+ uint32_t tickstart;
+ uint32_t fifoword;
+ uint8_t *pparams = ParametersTable;
+
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check the parameters */
+ assert_param(IS_DSI_LONG_WRITE_PACKET_TYPE(Mode));
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait for Command FIFO Empty */
+ while ((hdsi->Instance->GPSR & DSI_GPSR_CMDFE) == 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set the DCS code on payload byte 1, and the other parameters on the write FIFO command*/
+ fifoword = Param1;
+ nbBytes = (NbParams < 3U) ? NbParams : 3U;
+
+ for (count = 0U; count < nbBytes; count++)
+ {
+ fifoword |= (((uint32_t)(*(pparams + count))) << (8U + (8U * count)));
+ }
+ hdsi->Instance->GPDR = fifoword;
+
+ uicounter = NbParams - nbBytes;
+ pparams += nbBytes;
+ /* Set the Next parameters on the write FIFO command*/
+ while (uicounter != 0U)
+ {
+ nbBytes = (uicounter < 4U) ? uicounter : 4U;
+ fifoword = 0U;
+ for (count = 0U; count < nbBytes; count++)
+ {
+ fifoword |= (((uint32_t)(*(pparams + count))) << (8U * count));
+ }
+ hdsi->Instance->GPDR = fifoword;
+
+ uicounter -= nbBytes;
+ pparams += nbBytes;
+ }
+
+ /* Configure the packet to send a long DCS command */
+ DSI_ConfigPacketHeader(hdsi->Instance,
+ ChannelID,
+ Mode,
+ ((NbParams + 1U) & 0x00FFU),
+ (((NbParams + 1U) & 0xFF00U) >> 8U));
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Read command (DCS or generic)
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param ChannelNbr Virtual channel ID
+ * @param Array pointer to a buffer to store the payload of a read back operation.
+ * @param Size Data size to be read (in byte).
+ * @param Mode DSI read packet data type.
+ * This parameter can be any value of @arg DSI_SHORT_READ_PKT_Data_Type.
+ * @param DCSCmd DCS get/read command.
+ * @param ParametersTable Pointer to parameter values table.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_Read(DSI_HandleTypeDef *hdsi,
+ uint32_t ChannelNbr,
+ uint8_t *Array,
+ uint32_t Size,
+ uint32_t Mode,
+ uint32_t DCSCmd,
+ uint8_t *ParametersTable)
+{
+ uint32_t tickstart;
+ uint8_t *pdata = Array;
+ uint32_t datasize = Size;
+ uint32_t fifoword;
+ uint32_t nbbytes;
+ uint32_t count;
+
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check the parameters */
+ assert_param(IS_DSI_READ_PACKET_TYPE(Mode));
+
+ if (datasize > 2U)
+ {
+ /* set max return packet size */
+ if (DSI_ShortWrite(hdsi, ChannelNbr, DSI_MAX_RETURN_PKT_SIZE, ((datasize) & 0xFFU),
+ (((datasize) >> 8U) & 0xFFU)) != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Configure the packet to read command */
+ if (Mode == DSI_DCS_SHORT_PKT_READ)
+ {
+ DSI_ConfigPacketHeader(hdsi->Instance, ChannelNbr, Mode, DCSCmd, 0U);
+ }
+ else if (Mode == DSI_GEN_SHORT_PKT_READ_P0)
+ {
+ DSI_ConfigPacketHeader(hdsi->Instance, ChannelNbr, Mode, 0U, 0U);
+ }
+ else if (Mode == DSI_GEN_SHORT_PKT_READ_P1)
+ {
+ DSI_ConfigPacketHeader(hdsi->Instance, ChannelNbr, Mode, ParametersTable[0U], 0U);
+ }
+ else if (Mode == DSI_GEN_SHORT_PKT_READ_P2)
+ {
+ DSI_ConfigPacketHeader(hdsi->Instance, ChannelNbr, Mode, ParametersTable[0U], ParametersTable[1U]);
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* If DSI fifo is not empty, read requested bytes */
+ while (((int32_t)(datasize)) > 0)
+ {
+ if ((hdsi->Instance->GPSR & DSI_GPSR_PRDFE) == 0U)
+ {
+ fifoword = hdsi->Instance->GPDR;
+ nbbytes = (datasize < 4U) ? datasize : 4U;
+
+ for (count = 0U; count < nbbytes; count++)
+ {
+ *pdata = (uint8_t)(fifoword >> (8U * count));
+ pdata++;
+ datasize--;
+ }
+ }
+
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enter the ULPM (Ultra Low Power Mode) with the D-PHY PLL running
+ * (only data lanes are in ULPM)
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_EnterULPMData(DSI_HandleTypeDef *hdsi)
+{
+ uint32_t tickstart;
+
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* ULPS Request on Data Lanes */
+ hdsi->Instance->PUCR |= DSI_PUCR_URDL;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until the D-PHY active lanes enter into ULPM */
+ if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE)
+ {
+ while ((hdsi->Instance->PSR & DSI_PSR_UAN0) != 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES)
+ {
+ while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Exit the ULPM (Ultra Low Power Mode) with the D-PHY PLL running
+ * (only data lanes are in ULPM)
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ExitULPMData(DSI_HandleTypeDef *hdsi)
+{
+ uint32_t tickstart;
+
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Exit ULPS on Data Lanes */
+ hdsi->Instance->PUCR |= DSI_PUCR_UEDL;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until all active lanes exit ULPM */
+ if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE)
+ {
+ while ((hdsi->Instance->PSR & DSI_PSR_UAN0) != DSI_PSR_UAN0)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES)
+ {
+ while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_UAN1))
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+
+ /* wait for 1 ms*/
+ HAL_Delay(1U);
+
+ /* De-assert the ULPM requests and the ULPM exit bits */
+ hdsi->Instance->PUCR = 0U;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enter the ULPM (Ultra Low Power Mode) with the D-PHY PLL turned off
+ * (both data and clock lanes are in ULPM)
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_EnterULPM(DSI_HandleTypeDef *hdsi)
+{
+ uint32_t tickstart;
+
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Clock lane configuration: no more HS request */
+ hdsi->Instance->CLCR &= ~DSI_CLCR_DPCC;
+
+ /* Use system PLL as byte lane clock source before stopping DSIPHY clock source */
+ __HAL_RCC_DSI_CONFIG(RCC_DSICLKSOURCE_PLL2);
+
+ /* ULPS Request on Clock and Data Lanes */
+ hdsi->Instance->PUCR |= (DSI_PUCR_URCL | DSI_PUCR_URDL);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until all active lanes exit ULPM */
+ if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE)
+ {
+ while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UANC)) != 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES)
+ {
+ while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1 | DSI_PSR_UANC)) != 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+
+ /* Turn off the DSI PLL */
+ __HAL_DSI_PLL_DISABLE(hdsi);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Exit the ULPM (Ultra Low Power Mode) with the D-PHY PLL turned off
+ * (both data and clock lanes are in ULPM)
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ExitULPM(DSI_HandleTypeDef *hdsi)
+{
+ uint32_t tickstart;
+
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Turn on the DSI PLL */
+ __HAL_DSI_PLL_ENABLE(hdsi);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait for the lock of the PLL */
+ while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Exit ULPS on Clock and Data Lanes */
+ hdsi->Instance->PUCR |= (DSI_PUCR_UECL | DSI_PUCR_UEDL);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until all active lanes exit ULPM */
+ if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE)
+ {
+ while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UANC)) != (DSI_PSR_UAN0 | DSI_PSR_UANC))
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES)
+ {
+ while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1 | DSI_PSR_UANC)) != (DSI_PSR_UAN0 | DSI_PSR_UAN1 |
+ DSI_PSR_UANC))
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+
+ /* wait for 1 ms */
+ HAL_Delay(1U);
+
+ /* De-assert the ULPM requests and the ULPM exit bits */
+ hdsi->Instance->PUCR = 0U;
+
+ /* Switch the lanbyteclock source in the RCC from system PLL to D-PHY */
+ __HAL_RCC_DSI_CONFIG(RCC_DSICLKSOURCE_PHY);
+
+ /* Restore clock lane configuration to HS */
+ hdsi->Instance->CLCR |= DSI_CLCR_DPCC;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start test pattern generation
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param Mode Pattern generator mode
+ * This parameter can be one of the following values:
+ * 0 : Color bars (horizontal or vertical)
+ * 1 : BER pattern (vertical only)
+ * @param Orientation Pattern generator orientation
+ * This parameter can be one of the following values:
+ * 0 : Vertical color bars
+ * 1 : Horizontal color bars
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_PatternGeneratorStart(DSI_HandleTypeDef *hdsi, uint32_t Mode, uint32_t Orientation)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Configure pattern generator mode and orientation */
+ hdsi->Instance->VMCR &= ~(DSI_VMCR_PGM | DSI_VMCR_PGO);
+ hdsi->Instance->VMCR |= ((Mode << 20U) | (Orientation << 24U));
+
+ /* Enable pattern generator by setting PGE bit */
+ hdsi->Instance->VMCR |= DSI_VMCR_PGE;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop test pattern generation
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_PatternGeneratorStop(DSI_HandleTypeDef *hdsi)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Disable pattern generator by clearing PGE bit */
+ hdsi->Instance->VMCR &= ~DSI_VMCR_PGE;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set Slew-Rate And Delay Tuning
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param CommDelay Communication delay to be adjusted.
+ * This parameter can be any value of @arg DSI_Communication_Delay
+ * @param Lane select between clock or data lanes.
+ * This parameter can be any value of @arg DSI_Lane_Group
+ * @param Value Custom value of the slew-rate or delay
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_SetSlewRateAndDelayTuning(DSI_HandleTypeDef *hdsi, uint32_t CommDelay, uint32_t Lane,
+ uint32_t Value)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check function parameters */
+ assert_param(IS_DSI_COMMUNICATION_DELAY(CommDelay));
+ assert_param(IS_DSI_LANE_GROUP(Lane));
+
+ switch (CommDelay)
+ {
+ case DSI_SLEW_RATE_HSTX:
+ if (Lane == DSI_CLOCK_LANE)
+ {
+ /* High-Speed Transmission Slew Rate Control on Clock Lane */
+ hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_HSTXSRCCL;
+ hdsi->Instance->WPCR[1U] |= Value << 16U;
+ }
+ else if (Lane == DSI_DATA_LANES)
+ {
+ /* High-Speed Transmission Slew Rate Control on Data Lanes */
+ hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_HSTXSRCDL;
+ hdsi->Instance->WPCR[1U] |= Value << 18U;
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+ break;
+ case DSI_SLEW_RATE_LPTX:
+ if (Lane == DSI_CLOCK_LANE)
+ {
+ /* Low-Power transmission Slew Rate Compensation on Clock Lane */
+ hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_LPSRCCL;
+ hdsi->Instance->WPCR[1U] |= Value << 6U;
+ }
+ else if (Lane == DSI_DATA_LANES)
+ {
+ /* Low-Power transmission Slew Rate Compensation on Data Lanes */
+ hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_LPSRCDL;
+ hdsi->Instance->WPCR[1U] |= Value << 8U;
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+ break;
+ case DSI_HS_DELAY:
+ if (Lane == DSI_CLOCK_LANE)
+ {
+ /* High-Speed Transmission Delay on Clock Lane */
+ hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_HSTXDCL;
+ hdsi->Instance->WPCR[1U] |= Value;
+ }
+ else if (Lane == DSI_DATA_LANES)
+ {
+ /* High-Speed Transmission Delay on Data Lanes */
+ hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_HSTXDDL;
+ hdsi->Instance->WPCR[1U] |= Value << 2U;
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Low-Power Reception Filter Tuning
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param Frequency cutoff frequency of low-pass filter at the input of LPRX
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_SetLowPowerRXFilter(DSI_HandleTypeDef *hdsi, uint32_t Frequency)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Low-Power RX low-pass Filtering Tuning */
+ hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_LPRXFT;
+ hdsi->Instance->WPCR[1U] |= Frequency << 25U;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Activate an additional current path on all lanes to meet the SDDTx parameter
+ * defined in the MIPI D-PHY specification
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param State ENABLE or DISABLE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_SetSDD(DSI_HandleTypeDef *hdsi, FunctionalState State)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(State));
+
+ /* Activate/Disactivate additional current path on all lanes */
+ hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_SDDC;
+ hdsi->Instance->WPCR[1U] |= ((uint32_t)State << 12U);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Custom lane pins configuration
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param CustomLane Function to be applyed on selected lane.
+ * This parameter can be any value of @arg DSI_CustomLane
+ * @param Lane select between clock or data lane 0 or data lane 1.
+ * This parameter can be any value of @arg DSI_Lane_Select
+ * @param State ENABLE or DISABLE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_SetLanePinsConfiguration(DSI_HandleTypeDef *hdsi, uint32_t CustomLane, uint32_t Lane,
+ FunctionalState State)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check function parameters */
+ assert_param(IS_DSI_CUSTOM_LANE(CustomLane));
+ assert_param(IS_DSI_LANE(Lane));
+ assert_param(IS_FUNCTIONAL_STATE(State));
+
+ switch (CustomLane)
+ {
+ case DSI_SWAP_LANE_PINS:
+ if (Lane == DSI_CLK_LANE)
+ {
+ /* Swap pins on clock lane */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_SWCL;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 6U);
+ }
+ else if (Lane == DSI_DATA_LANE0)
+ {
+ /* Swap pins on data lane 0 */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_SWDL0;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 7U);
+ }
+ else if (Lane == DSI_DATA_LANE1)
+ {
+ /* Swap pins on data lane 1 */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_SWDL1;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 8U);
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+ break;
+ case DSI_INVERT_HS_SIGNAL:
+ if (Lane == DSI_CLK_LANE)
+ {
+ /* Invert HS signal on clock lane */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_HSICL;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 9U);
+ }
+ else if (Lane == DSI_DATA_LANE0)
+ {
+ /* Invert HS signal on data lane 0 */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_HSIDL0;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 10U);
+ }
+ else if (Lane == DSI_DATA_LANE1)
+ {
+ /* Invert HS signal on data lane 1 */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_HSIDL1;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 11U);
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set custom timing for the PHY
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param Timing PHY timing to be adjusted.
+ * This parameter can be any value of @arg DSI_PHY_Timing
+ * @param State ENABLE or DISABLE
+ * @param Value Custom value of the timing
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_SetPHYTimings(DSI_HandleTypeDef *hdsi, uint32_t Timing, FunctionalState State, uint32_t Value)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check function parameters */
+ assert_param(IS_DSI_PHY_TIMING(Timing));
+ assert_param(IS_FUNCTIONAL_STATE(State));
+
+ switch (Timing)
+ {
+ case DSI_TCLK_POST:
+ /* Enable/Disable custom timing setting */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TCLKPOSTEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 27U);
+
+ if (State != DISABLE)
+ {
+ /* Set custom value */
+ hdsi->Instance->WPCR[4U] &= ~DSI_WPCR4_TCLKPOST;
+ hdsi->Instance->WPCR[4U] |= Value & DSI_WPCR4_TCLKPOST;
+ }
+
+ break;
+ case DSI_TLPX_CLK:
+ /* Enable/Disable custom timing setting */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TLPXCEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 26U);
+
+ if (State != DISABLE)
+ {
+ /* Set custom value */
+ hdsi->Instance->WPCR[3U] &= ~DSI_WPCR3_TLPXC;
+ hdsi->Instance->WPCR[3U] |= (Value << 24U) & DSI_WPCR3_TLPXC;
+ }
+
+ break;
+ case DSI_THS_EXIT:
+ /* Enable/Disable custom timing setting */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_THSEXITEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 25U);
+
+ if (State != DISABLE)
+ {
+ /* Set custom value */
+ hdsi->Instance->WPCR[3U] &= ~DSI_WPCR3_THSEXIT;
+ hdsi->Instance->WPCR[3U] |= (Value << 16U) & DSI_WPCR3_THSEXIT;
+ }
+
+ break;
+ case DSI_TLPX_DATA:
+ /* Enable/Disable custom timing setting */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TLPXDEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 24U);
+
+ if (State != DISABLE)
+ {
+ /* Set custom value */
+ hdsi->Instance->WPCR[3U] &= ~DSI_WPCR3_TLPXD;
+ hdsi->Instance->WPCR[3U] |= (Value << 8U) & DSI_WPCR3_TLPXD;
+ }
+
+ break;
+ case DSI_THS_ZERO:
+ /* Enable/Disable custom timing setting */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_THSZEROEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 23U);
+
+ if (State != DISABLE)
+ {
+ /* Set custom value */
+ hdsi->Instance->WPCR[3U] &= ~DSI_WPCR3_THSZERO;
+ hdsi->Instance->WPCR[3U] |= Value & DSI_WPCR3_THSZERO;
+ }
+
+ break;
+ case DSI_THS_TRAIL:
+ /* Enable/Disable custom timing setting */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_THSTRAILEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 22U);
+
+ if (State != DISABLE)
+ {
+ /* Set custom value */
+ hdsi->Instance->WPCR[2U] &= ~DSI_WPCR2_THSTRAIL;
+ hdsi->Instance->WPCR[2U] |= (Value << 24U) & DSI_WPCR2_THSTRAIL;
+ }
+
+ break;
+ case DSI_THS_PREPARE:
+ /* Enable/Disable custom timing setting */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_THSPREPEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 21U);
+
+ if (State != DISABLE)
+ {
+ /* Set custom value */
+ hdsi->Instance->WPCR[2U] &= ~DSI_WPCR2_THSPREP;
+ hdsi->Instance->WPCR[2U] |= (Value << 16U) & DSI_WPCR2_THSPREP;
+ }
+
+ break;
+ case DSI_TCLK_ZERO:
+ /* Enable/Disable custom timing setting */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TCLKZEROEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 20U);
+
+ if (State != DISABLE)
+ {
+ /* Set custom value */
+ hdsi->Instance->WPCR[2U] &= ~DSI_WPCR2_TCLKZERO;
+ hdsi->Instance->WPCR[2U] |= (Value << 8U) & DSI_WPCR2_TCLKZERO;
+ }
+
+ break;
+ case DSI_TCLK_PREPARE:
+ /* Enable/Disable custom timing setting */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TCLKPREPEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 19U);
+
+ if (State != DISABLE)
+ {
+ /* Set custom value */
+ hdsi->Instance->WPCR[2U] &= ~DSI_WPCR2_TCLKPREP;
+ hdsi->Instance->WPCR[2U] |= Value & DSI_WPCR2_TCLKPREP;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Force the Clock/Data Lane in TX Stop Mode
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param Lane select between clock or data lanes.
+ * This parameter can be any value of @arg DSI_Lane_Group
+ * @param State ENABLE or DISABLE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ForceTXStopMode(DSI_HandleTypeDef *hdsi, uint32_t Lane, FunctionalState State)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check function parameters */
+ assert_param(IS_DSI_LANE_GROUP(Lane));
+ assert_param(IS_FUNCTIONAL_STATE(State));
+
+ if (Lane == DSI_CLOCK_LANE)
+ {
+ /* Force/Unforce the Clock Lane in TX Stop Mode */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_FTXSMCL;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 12U);
+ }
+ else if (Lane == DSI_DATA_LANES)
+ {
+ /* Force/Unforce the Data Lanes in TX Stop Mode */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_FTXSMDL;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 13U);
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_ERROR;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Force LP Receiver in Low-Power Mode
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param State ENABLE or DISABLE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ForceRXLowPower(DSI_HandleTypeDef *hdsi, FunctionalState State)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(State));
+
+ /* Force/Unforce LP Receiver in Low-Power Mode */
+ hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_FLPRXLPM;
+ hdsi->Instance->WPCR[1U] |= ((uint32_t)State << 22U);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Force Data Lanes in RX Mode after a BTA
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param State ENABLE or DISABLE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_ForceDataLanesInRX(DSI_HandleTypeDef *hdsi, FunctionalState State)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(State));
+
+ /* Force Data Lanes in RX Mode */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TDDL;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 16U);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable a pull-down on the lanes to prevent from floating states when unused
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param State ENABLE or DISABLE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_SetPullDown(DSI_HandleTypeDef *hdsi, FunctionalState State)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(State));
+
+ /* Enable/Disable pull-down on lanes */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_PDEN;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 18U);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Switch off the contention detection on data lanes
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @param State ENABLE or DISABLE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DSI_SetContentionDetectionOff(DSI_HandleTypeDef *hdsi, FunctionalState State)
+{
+ /* Process locked */
+ __HAL_LOCK(hdsi);
+
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(State));
+
+ /* Contention Detection on Data Lanes OFF */
+ hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_CDOFFDL;
+ hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 14U);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdsi);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DSI_Group4 Peripheral State and Errors functions
+ * @brief Peripheral State and Errors functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Check the DSI state.
+ (+) Get error code.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the DSI state
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval HAL state
+ */
+HAL_DSI_StateTypeDef HAL_DSI_GetState(DSI_HandleTypeDef *hdsi)
+{
+ return hdsi->State;
+}
+
+/**
+ * @brief Return the DSI error code
+ * @param hdsi pointer to a DSI_HandleTypeDef structure that contains
+ * the configuration information for the DSI.
+ * @retval DSI Error Code
+ */
+uint32_t HAL_DSI_GetError(DSI_HandleTypeDef *hdsi)
+{
+ /* Get the error code */
+ return hdsi->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* DSI */
+
+#endif /* HAL_DSI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_dts.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dts.c
new file mode 100644
index 0000000000..a6227c7c21
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_dts.c
@@ -0,0 +1,823 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dts.c
+ * @author MCD Application Team
+ * @brief DTS HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the DTS peripheral:
+ * + Initialization and de-initialization functions
+ * + Start/Stop operation functions in polling mode.
+ * + Start/Stop operation functions in interrupt mode.
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+================================================================================
+ ##### DTS Peripheral features #####
+================================================================================
+
+ [..]
+ The STM32h7xx device family integrate one DTS sensor interface :
+
+
+ ##### How to use this driver #####
+================================================================================
+ [..]
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_DTS_MODULE_ENABLED
+
+#if defined(DTS)
+
+/** @defgroup DTS DTS
+ * @brief DTS HAL module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup DTS_Private_Constants
+ * @{
+ */
+
+/* @brief Delay for DTS startup time
+ * @note Delay required to get ready for DTS Block.
+ * @note Unit: ms
+ */
+#define DTS_DELAY_STARTUP (1UL)
+
+/* @brief DTS measure ready flag time out value.
+ * @note Maximal measurement time is when LSE is selected as ref_clock and
+ * maximal sampling time is used, taking calibration into account this
+ * is equivalent to ~620 us. Use 5 ms as arbitrary timeout
+ * @note Unit: ms
+ */
+#define TS_TIMEOUT_MS (5UL)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+static void DTS_ResetCallback(DTS_HandleTypeDef *hdts);
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup DTS_Exported_Functions DTS Exported Functions
+ * @{
+ */
+
+/** @defgroup DTS_Exported_Functions_Group1 Initialization/de-initialization functions
+ * @brief Initialization and de-initialization functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions to initialize and de-initialize comparators
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the DTS according to the specified
+ * parameters in the DTS_InitTypeDef and initialize the associated handle.
+ * @param hdts DTS handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DTS_Init(DTS_HandleTypeDef *hdts)
+{
+ /* Check the DTS handle allocation */
+ if (hdts == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_DTS_ALL_INSTANCE(hdts->Instance));
+ assert_param(IS_DTS_QUICKMEAS(hdts->Init.QuickMeasure));
+ assert_param(IS_DTS_REFCLK(hdts->Init.RefClock));
+ assert_param(IS_DTS_TRIGGERINPUT(hdts->Init.TriggerInput));
+ assert_param(IS_DTS_SAMPLINGTIME(hdts->Init.SamplingTime));
+ assert_param(IS_DTS_THRESHOLD(hdts->Init.HighThreshold));
+ assert_param(IS_DTS_THRESHOLD(hdts->Init.LowThreshold));
+
+ if (hdts->State == HAL_DTS_STATE_RESET)
+ {
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+ /* Reset interrupt callbacks to legacy weak callbacks */
+ DTS_ResetCallback(hdts);
+
+ if (hdts->MspInitCallback == NULL)
+ {
+ hdts->MspInitCallback = HAL_DTS_MspInit;
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ hdts->MspInitCallback(hdts);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ HAL_DTS_MspInit(hdts);
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+ }
+
+ /* Change the DTS state */
+ hdts->State = HAL_DTS_STATE_BUSY;
+
+ /* Check ramp coefficient */
+ if (hdts->Instance->RAMPVALR == 0UL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check factory calibration temperature */
+ if (hdts->Instance->T0VALR1 == 0UL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check Quick Measure option is enabled or disabled */
+ if (hdts->Init.QuickMeasure == DTS_QUICKMEAS_DISABLE)
+ {
+ /* Check Reference clock selection */
+ if (hdts->Init.RefClock == DTS_REFCLKSEL_PCLK)
+ {
+ assert_param(IS_DTS_DIVIDER_RATIO_NUMBER(hdts->Init.Divider));
+ }
+ /* Quick measurement mode disabled */
+ CLEAR_BIT(hdts->Instance->CFGR1, DTS_CFGR1_Q_MEAS_OPT);
+ }
+ else
+ {
+ /* DTS_QUICKMEAS_ENABLE shall be used only when the LSE clock is
+ selected as reference clock */
+ if (hdts->Init.RefClock != DTS_REFCLKSEL_LSE)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Quick measurement mode enabled - no calibration needed */
+ SET_BIT(hdts->Instance->CFGR1, DTS_CFGR1_Q_MEAS_OPT);
+ }
+
+ /* set the DTS clk source */
+ if (hdts->Init.RefClock == DTS_REFCLKSEL_LSE)
+ {
+ SET_BIT(hdts->Instance->CFGR1, DTS_CFGR1_REFCLK_SEL);
+ }
+ else
+ {
+ CLEAR_BIT(hdts->Instance->CFGR1, DTS_CFGR1_REFCLK_SEL);
+ }
+
+ MODIFY_REG(hdts->Instance->CFGR1, DTS_CFGR1_HSREF_CLK_DIV, (hdts->Init.Divider << DTS_CFGR1_HSREF_CLK_DIV_Pos));
+ MODIFY_REG(hdts->Instance->CFGR1, DTS_CFGR1_TS1_SMP_TIME, hdts->Init.SamplingTime);
+ MODIFY_REG(hdts->Instance->CFGR1, DTS_CFGR1_TS1_INTRIG_SEL, hdts->Init.TriggerInput);
+ MODIFY_REG(hdts->Instance->ITR1, DTS_ITR1_TS1_HITTHD, (hdts->Init.HighThreshold << DTS_ITR1_TS1_HITTHD_Pos));
+ MODIFY_REG(hdts->Instance->ITR1, DTS_ITR1_TS1_LITTHD, hdts->Init.LowThreshold);
+
+ /* Change the DTS state */
+ hdts->State = HAL_DTS_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the DTS peripheral.
+ * @note Deinitialization cannot be performed if the DTS configuration is locked.
+ * To unlock the configuration, perform a system reset.
+ * @param hdts DTS handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DTS_DeInit(DTS_HandleTypeDef *hdts)
+{
+ /* Check the DTS handle allocation */
+ if (hdts == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameter */
+ assert_param(IS_DTS_ALL_INSTANCE(hdts->Instance));
+
+ /* Set DTS_CFGR register to reset value */
+ CLEAR_REG(hdts->Instance->CFGR1);
+
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+ if (hdts->MspDeInitCallback == NULL)
+ {
+ hdts->MspDeInitCallback = HAL_DTS_MspDeInit;
+ }
+
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ hdts->MspDeInitCallback(hdts);
+#else
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ HAL_DTS_MspDeInit(hdts);
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+
+ hdts->State = HAL_DTS_STATE_RESET;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the DTS MSP.
+ * @param hdts DTS handle
+ * @retval None
+ */
+__weak void HAL_DTS_MspInit(DTS_HandleTypeDef *hdts)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdts);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DTS_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the DTS MSP.
+ * @param hdts DTS handle
+ * @retval None
+ */
+__weak void HAL_DTS_MspDeInit(DTS_HandleTypeDef *hdts)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdts);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DTS_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DTS_Exported_Functions_Group2 Start-Stop operation functions
+ * @brief Start-Stop operation functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### DTS Start Stop operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start a DTS Sensor without interrupt.
+ (+) Stop a DTS Sensor without interrupt.
+ (+) Start a DTS Sensor with interrupt generation.
+ (+) Stop a DTS Sensor with interrupt generation.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the DTS sensor.
+ * @param hdts DTS handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DTS_Start(DTS_HandleTypeDef *hdts)
+{
+ uint32_t Ref_Time;
+
+ /* Check the DTS handle allocation */
+ if (hdts == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hdts->State == HAL_DTS_STATE_READY)
+ {
+ hdts->State = HAL_DTS_STATE_BUSY;
+
+ /* Enable DTS sensor */
+ __HAL_DTS_ENABLE(hdts);
+
+ /* Get Start Tick*/
+ Ref_Time = HAL_GetTick();
+
+ /* Wait till TS1_RDY flag is set */
+ while (__HAL_DTS_GET_FLAG(hdts, DTS_FLAG_TS1_RDY) == RESET)
+ {
+ if ((HAL_GetTick() - Ref_Time) > DTS_DELAY_STARTUP)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ if (__HAL_DTS_GET_TRIGGER(hdts) == DTS_TRIGGER_HW_NONE)
+ {
+ /* Start continuous measures */
+ SET_BIT(hdts->Instance->CFGR1, DTS_CFGR1_TS1_START);
+
+ /* Ensure start is taken into account */
+ HAL_Delay(TS_TIMEOUT_MS);
+ }
+
+ hdts->State = HAL_DTS_STATE_READY;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the DTS Sensor.
+ * @param hdts DTS handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DTS_Stop(DTS_HandleTypeDef *hdts)
+{
+ /* Check the DTS handle allocation */
+ if (hdts == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hdts->State == HAL_DTS_STATE_READY)
+ {
+ hdts->State = HAL_DTS_STATE_BUSY;
+
+ if (__HAL_DTS_GET_TRIGGER(hdts) == DTS_TRIGGER_HW_NONE)
+ {
+ CLEAR_BIT(hdts->Instance->CFGR1, DTS_CFGR1_TS1_START);
+ }
+
+ /* Disable the selected DTS sensor */
+ __HAL_DTS_DISABLE(hdts);
+
+ hdts->State = HAL_DTS_STATE_READY;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the interrupt(s) and start the DTS sensor
+ * @param hdts DTS handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DTS_Start_IT(DTS_HandleTypeDef *hdts)
+{
+ uint32_t Ref_Time;
+
+ /* Check the DTS handle allocation */
+ if (hdts == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hdts->State == HAL_DTS_STATE_READY)
+ {
+ hdts->State = HAL_DTS_STATE_BUSY;
+
+ /* On Asynchronous mode enable the asynchronous IT */
+ if (hdts->Init.RefClock == DTS_REFCLKSEL_LSE)
+ {
+ __HAL_DTS_ENABLE_IT(hdts, DTS_IT_TS1_AITE | DTS_IT_TS1_AITL | DTS_IT_TS1_AITH);
+ }
+ else
+ {
+ /* Enable the IT(s) */
+ __HAL_DTS_ENABLE_IT(hdts, DTS_IT_TS1_ITE | DTS_IT_TS1_ITL | DTS_IT_TS1_ITH);
+ }
+
+ /* Enable the selected DTS sensor */
+ __HAL_DTS_ENABLE(hdts);
+
+ /* Get Start Tick*/
+ Ref_Time = HAL_GetTick();
+
+ /* Wait till TS1_RDY flag is set */
+ while (__HAL_DTS_GET_FLAG(hdts, DTS_FLAG_TS1_RDY) == RESET)
+ {
+ if ((HAL_GetTick() - Ref_Time) > DTS_DELAY_STARTUP)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ if (__HAL_DTS_GET_TRIGGER(hdts) == DTS_TRIGGER_HW_NONE)
+ {
+ /* Start continuous measures */
+ SET_BIT(hdts->Instance->CFGR1, DTS_CFGR1_TS1_START);
+
+ /* Ensure start is taken into account */
+ HAL_Delay(TS_TIMEOUT_MS);
+ }
+
+ hdts->State = HAL_DTS_STATE_READY;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the interrupt(s) and stop the DTS sensor.
+ * @param hdts DTS handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DTS_Stop_IT(DTS_HandleTypeDef *hdts)
+{
+ /* Check the DTS handle allocation */
+ if (hdts == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hdts->State == HAL_DTS_STATE_READY)
+ {
+ hdts->State = HAL_DTS_STATE_BUSY;
+
+ /* On Asynchronous mode disable the asynchronous IT */
+ if (hdts->Init.RefClock == DTS_REFCLKSEL_LSE)
+ {
+ __HAL_DTS_DISABLE_IT(hdts, DTS_IT_TS1_AITE | DTS_IT_TS1_AITL | DTS_IT_TS1_AITH);
+ }
+ else
+ {
+ /* Disable the IT(s) */
+ __HAL_DTS_DISABLE_IT(hdts, DTS_IT_TS1_ITE | DTS_IT_TS1_ITL | DTS_IT_TS1_ITH);
+ }
+
+ if (__HAL_DTS_GET_TRIGGER(hdts) == DTS_TRIGGER_HW_NONE)
+ {
+ CLEAR_BIT(hdts->Instance->CFGR1, DTS_CFGR1_TS1_START);
+ }
+
+ /* Disable the selected DTS sensor */
+ __HAL_DTS_DISABLE(hdts);
+
+ hdts->State = HAL_DTS_STATE_READY;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get temperature from DTS
+ * @param hdts DTS handle
+ * @param Temperature Temperature in deg C
+ * @note This function retrieves latest available measure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DTS_GetTemperature(DTS_HandleTypeDef *hdts, int32_t *Temperature)
+{
+ uint32_t freq_meas;
+ uint32_t samples;
+ uint32_t t0_temp;
+ uint32_t t0_freq;
+ uint32_t ramp_coeff;
+
+ if (hdts->State == HAL_DTS_STATE_READY)
+ {
+ hdts->State = HAL_DTS_STATE_BUSY;
+
+ /* Get the total number of samples */
+ samples = (hdts->Instance->DR & DTS_DR_TS1_MFREQ);
+
+ if ((hdts->Init.SamplingTime == 0UL) || (samples == 0UL))
+ {
+ hdts->State = HAL_DTS_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ if ((hdts->Init.RefClock) == DTS_REFCLKSEL_LSE)
+ {
+ freq_meas = (LSE_VALUE * samples) / (hdts->Init.SamplingTime >> DTS_CFGR1_TS1_SMP_TIME_Pos); /* On Hz */
+ }
+ else
+ {
+ freq_meas = (HAL_RCCEx_GetD3PCLK1Freq() * (hdts->Init.SamplingTime >> DTS_CFGR1_TS1_SMP_TIME_Pos)) / samples; /* On Hz */
+ }
+
+ /* Read factory settings */
+ t0_temp = hdts->Instance->T0VALR1 >> DTS_T0VALR1_TS1_T0_Pos;
+
+ if (t0_temp == 0UL)
+ {
+ t0_temp = 30UL; /* 30 deg C */
+ }
+ else if (t0_temp == 1UL)
+ {
+ t0_temp = 110UL; /* 110 deg C */
+ }
+ else
+ {
+ hdts->State = HAL_DTS_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ t0_freq = (hdts->Instance->T0VALR1 & DTS_T0VALR1_TS1_FMT0) * 100UL; /* Hz */
+
+ ramp_coeff = hdts->Instance->RAMPVALR & DTS_RAMPVALR_TS1_RAMP_COEFF; /* deg C/Hz */
+
+ if (ramp_coeff == 0UL)
+ {
+ hdts->State = HAL_DTS_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Figure out the temperature deg C */
+ *Temperature = (int32_t)t0_temp + (((int32_t)freq_meas - (int32_t)t0_freq) / (int32_t)ramp_coeff);
+
+ hdts->State = HAL_DTS_STATE_READY;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DTS sensor IRQ Handler.
+ * @param hdts DTS handle
+ * @retval None
+ */
+void HAL_DTS_IRQHandler(DTS_HandleTypeDef *hdts)
+{
+ /* Check end of measure Asynchronous IT */
+ if ((__HAL_DTS_GET_FLAG(hdts, DTS_FLAG_TS1_AITE)) != RESET)
+ {
+ __HAL_DTS_CLEAR_FLAG(hdts, DTS_FLAG_TS1_AITE);
+
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+ hdts->AsyncEndCallback(hdts);
+#else
+ HAL_DTS_AsyncEndCallback(hdts);
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+ }
+
+ /* Check low threshold Asynchronous IT */
+ if ((__HAL_DTS_GET_FLAG(hdts, DTS_FLAG_TS1_AITL)) != RESET)
+ {
+ __HAL_DTS_CLEAR_FLAG(hdts, DTS_FLAG_TS1_AITL);
+
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+ hdts->AsyncLowCallback(hdts);
+#else
+ HAL_DTS_AsyncLowCallback(hdts);
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+ }
+
+ /* Check high threshold Asynchronous IT */
+ if ((__HAL_DTS_GET_FLAG(hdts, DTS_FLAG_TS1_AITH)) != RESET)
+ {
+ __HAL_DTS_CLEAR_FLAG(hdts, DTS_FLAG_TS1_AITH);
+
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+ hdts->AsyncHighCallback(hdts);
+#else
+ HAL_DTS_AsyncHighCallback(hdts);
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+ }
+
+ /* Check end of measure IT */
+ if ((__HAL_DTS_GET_FLAG(hdts, DTS_FLAG_TS1_ITE)) != RESET)
+ {
+ __HAL_DTS_CLEAR_FLAG(hdts, DTS_FLAG_TS1_ITE);
+
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+ hdts->EndCallback(hdts);
+#else
+ HAL_DTS_EndCallback(hdts);
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+ }
+
+ /* Check low threshold IT */
+ if ((__HAL_DTS_GET_FLAG(hdts, DTS_FLAG_TS1_ITL)) != RESET)
+ {
+ __HAL_DTS_CLEAR_FLAG(hdts, DTS_FLAG_TS1_ITL);
+
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+ hdts->LowCallback(hdts);
+#else
+ HAL_DTS_LowCallback(hdts);
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+ }
+
+ /* Check high threshold IT */
+ if ((__HAL_DTS_GET_FLAG(hdts, DTS_FLAG_TS1_ITH)) != RESET)
+ {
+ __HAL_DTS_CLEAR_FLAG(hdts, DTS_FLAG_TS1_ITH);
+
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+ hdts->HighCallback(hdts);
+#else
+ HAL_DTS_HighCallback(hdts);
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief DTS Sensor End measure callback.
+ * @param hdts DTS handle
+ * @retval None
+ */
+__weak void HAL_DTS_EndCallback(DTS_HandleTypeDef *hdts)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdts);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DTS_EndCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief DTS Sensor low threshold measure callback.
+ * @param hdts DTS handle
+ * @retval None
+ */
+__weak void HAL_DTS_LowCallback(DTS_HandleTypeDef *hdts)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdts);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DTS_LowCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief DTS Sensor high threshold measure callback.
+ * @param hdts DTS handle
+ * @retval None
+ */
+__weak void HAL_DTS_HighCallback(DTS_HandleTypeDef *hdts)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdts);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DTS_HighCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief DTS Sensor asynchronous end measure callback.
+ * @param hdts DTS handle
+ * @retval None
+ */
+__weak void HAL_DTS_AsyncEndCallback(DTS_HandleTypeDef *hdts)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdts);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DTS_AsyncEndCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief DTS Sensor asynchronous low threshold measure callback.
+ * @param hdts DTS handle
+ * @retval None
+ */
+__weak void HAL_DTS_AsyncLowCallback(DTS_HandleTypeDef *hdts)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdts);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DTS_AsyncLowCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief DTS Sensor asynchronous high threshold measure callback.
+ * @param hdts DTS handle
+ * @retval None
+ */
+__weak void HAL_DTS_AsyncHighCallback(DTS_HandleTypeDef *hdts)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdts);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DTS_AsyncHighCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DTS_Exported_Functions_Group3 Peripheral State functions
+ * @brief Peripheral State functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the DTS handle state.
+ * @param hdts DTS handle
+ * @retval HAL state
+ */
+HAL_DTS_StateTypeDef HAL_DTS_GetState(DTS_HandleTypeDef *hdts)
+{
+ /* Check the DTS handle allocation */
+ if (hdts == NULL)
+ {
+ return HAL_DTS_STATE_RESET;
+ }
+
+ /* Return DTS handle state */
+ return hdts->State;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup DTS_Private_Functions DTS Private Functions
+ * @{
+ */
+#if (USE_HAL_DTS_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Reset interrupt callbacks to the legacy weak callbacks.
+ * @param hdts pointer to a DTS_HandleTypeDef structure that contains
+ * the configuration information for DTS module.
+ * @retval None
+ */
+static void DTS_ResetCallback(DTS_HandleTypeDef *hdts)
+{
+ /* Reset the DTS callback to the legacy weak callbacks */
+ hdts->DTS_EndCallback = HAL_DTS_EndCallback; /* End measure Callback */
+ hdts->DTS_LowCallback = HAL_DTS_LowCallback; /* low threshold Callback */
+ hdts->DTS_HighCallback = HAL_DTS_HighCallback; /* high threshold Callback */
+ hdts->DTS_AsyncEndCallback = HAL_DTS_AsyncEndCallback; /* Asynchronous end of measure Callback */
+ hdts->DTS_AsyncLowCallback = HAL_DTS_AsyncLowCallback; /* Asynchronous low threshold Callback */
+ hdts->DTS_AsyncHighCallback = HAL_DTS_AsyncHighCallback; /* Asynchronous high threshold Callback */
+}
+#endif /* USE_HAL_DTS_REGISTER_CALLBACKS */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* DTS */
+
+#endif /* HAL_DTS_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_eth.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_eth.c
new file mode 100644
index 0000000000..afb215d042
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_eth.c
@@ -0,0 +1,2998 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_eth.c
+ * @author MCD Application Team
+ * @brief ETH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Ethernet (ETH) peripheral:
+ * + Initialization and deinitialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The ETH HAL driver can be used as follows:
+
+ (#)Declare a ETH_HandleTypeDef handle structure, for example:
+ ETH_HandleTypeDef heth;
+
+ (#)Fill parameters of Init structure in heth handle
+
+ (#)Call HAL_ETH_Init() API to initialize the Ethernet peripheral (MAC, DMA, ...)
+
+ (#)Initialize the ETH low level resources through the HAL_ETH_MspInit() API:
+ (##) Enable the Ethernet interface clock using
+ (+++) __HAL_RCC_ETH1MAC_CLK_ENABLE()
+ (+++) __HAL_RCC_ETH1TX_CLK_ENABLE()
+ (+++) __HAL_RCC_ETH1RX_CLK_ENABLE()
+
+ (##) Initialize the related GPIO clocks
+ (##) Configure Ethernet pinout
+ (##) Configure Ethernet NVIC interrupt (in Interrupt mode)
+
+ (#) Ethernet data reception is asynchronous, so call the following API
+ to start the listening mode:
+ (##) HAL_ETH_Start():
+ This API starts the MAC and DMA transmission and reception process,
+ without enabling end of transfer interrupts, in this mode user
+ has to poll for data availability by calling HAL_ETH_IsRxDataAvailable()
+ (##) HAL_ETH_Start_IT():
+ This API starts the MAC and DMA transmission and reception process,
+ end of transfer interrupts are enabled in this mode,
+ HAL_ETH_RxCpltCallback() will be executed when an Ethernet packet is received
+
+ (#) When data is received (HAL_ETH_IsRxDataAvailable() returns 1 or Rx interrupt
+ occurred), user can call the following APIs to get received data:
+ (##) HAL_ETH_GetRxDataBuffer(): Get buffer address of received frame
+ (##) HAL_ETH_GetRxDataLength(): Get received frame length
+ (##) HAL_ETH_GetRxDataInfo(): Get received frame additional info,
+ please refer to ETH_RxPacketInfo typedef structure
+
+ (#) For transmission path, two APIs are available:
+ (##) HAL_ETH_Transmit(): Transmit an ETH frame in blocking mode
+ (##) HAL_ETH_Transmit_IT(): Transmit an ETH frame in interrupt mode,
+ HAL_ETH_TxCpltCallback() will be executed when end of transfer occur
+
+ (#) Communication with an external PHY device:
+ (##) HAL_ETH_ReadPHYRegister(): Read a register from an external PHY
+ (##) HAL_ETH_WritePHYRegister(): Write data to an external RHY register
+
+ (#) Configure the Ethernet MAC after ETH peripheral initialization
+ (##) HAL_ETH_GetMACConfig(): Get MAC actual configuration into ETH_MACConfigTypeDef
+ (##) HAL_ETH_SetMACConfig(): Set MAC configuration based on ETH_MACConfigTypeDef
+
+ (#) Configure the Ethernet DMA after ETH peripheral initialization
+ (##) HAL_ETH_GetDMAConfig(): Get DMA actual configuration into ETH_DMAConfigTypeDef
+ (##) HAL_ETH_SetDMAConfig(): Set DMA configuration based on ETH_DMAConfigTypeDef
+
+ -@- The PTP protocol offload APIs are not supported in this driver.
+
+ *** Callback registration ***
+ =============================================
+
+ The compilation define USE_HAL_ETH_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Function @ref HAL_ETH_RegisterCallback() to register an interrupt callback.
+
+ Function @ref HAL_ETH_RegisterCallback() allows to register following callbacks:
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) DMAErrorCallback : DMA Error Callback.
+ (+) MACErrorCallback : MAC Error Callback.
+ (+) PMTCallback : Power Management Callback
+ (+) EEECallback : EEE Callback.
+ (+) WakeUpCallback : Wake UP Callback
+ (+) MspInitCallback : MspInit Callback.
+ (+) MspDeInitCallback: MspDeInit Callback.
+
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function @ref HAL_ETH_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ @ref HAL_ETH_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) DMAErrorCallback : DMA Error Callback.
+ (+) MACErrorCallback : MAC Error Callback.
+ (+) PMTCallback : Power Management Callback
+ (+) EEECallback : EEE Callback.
+ (+) WakeUpCallback : Wake UP Callback
+ (+) MspInitCallback : MspInit Callback.
+ (+) MspDeInitCallback: MspDeInit Callback.
+
+ By default, after the HAL_ETH_Init and when the state is HAL_ETH_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples @ref HAL_ETH_TxCpltCallback(), @ref HAL_ETH_RxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak function in the HAL_ETH_Init/ @ref HAL_ETH_DeInit only when
+ these callbacks are null (not registered beforehand).
+ if not, MspInit or MspDeInit are not null, the HAL_ETH_Init/ @ref HAL_ETH_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in HAL_ETH_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_ETH_STATE_READY or HAL_ETH_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 @ref HAL_ETH_RegisterCallback() before calling @ref HAL_ETH_DeInit
+ or HAL_ETH_Init function.
+
+ When The compilation define USE_HAL_ETH_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#ifdef HAL_ETH_MODULE_ENABLED
+
+#if defined(ETH)
+
+/** @defgroup ETH ETH
+ * @brief ETH HAL module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup ETH_Private_Constants ETH Private Constants
+ * @{
+ */
+#define ETH_MACCR_MASK ((uint32_t)0xFFFB7F7CU)
+#define ETH_MACECR_MASK ((uint32_t)0x3F077FFFU)
+#define ETH_MACPFR_MASK ((uint32_t)0x800007FFU)
+#define ETH_MACWTR_MASK ((uint32_t)0x0000010FU)
+#define ETH_MACTFCR_MASK ((uint32_t)0xFFFF00F2U)
+#define ETH_MACRFCR_MASK ((uint32_t)0x00000003U)
+#define ETH_MTLTQOMR_MASK ((uint32_t)0x00000072U)
+#define ETH_MTLRQOMR_MASK ((uint32_t)0x0000007BU)
+
+#define ETH_DMAMR_MASK ((uint32_t)0x00007802U)
+#define ETH_DMASBMR_MASK ((uint32_t)0x0000D001U)
+#define ETH_DMACCR_MASK ((uint32_t)0x00013FFFU)
+#define ETH_DMACTCR_MASK ((uint32_t)0x003F1010U)
+#define ETH_DMACRCR_MASK ((uint32_t)0x803F0000U)
+#define ETH_MACPCSR_MASK (ETH_MACPCSR_PWRDWN | ETH_MACPCSR_RWKPKTEN | \
+ ETH_MACPCSR_MGKPKTEN | ETH_MACPCSR_GLBLUCAST | \
+ ETH_MACPCSR_RWKPFE)
+
+/* Timeout values */
+#define ETH_SWRESET_TIMEOUT ((uint32_t)500U)
+#define ETH_MDIO_BUS_TIMEOUT ((uint32_t)1000U)
+
+#define ETH_DMARXNDESCWBF_ERRORS_MASK ((uint32_t)(ETH_DMARXNDESCWBF_DE | ETH_DMARXNDESCWBF_RE | \
+ ETH_DMARXNDESCWBF_OE | ETH_DMARXNDESCWBF_RWT |\
+ ETH_DMARXNDESCWBF_GP | ETH_DMARXNDESCWBF_CE))
+
+#define ETH_MAC_US_TICK ((uint32_t)1000000U)
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup ETH_Private_Macros ETH Private Macros
+ * @{
+ */
+/* Helper macros for TX descriptor handling */
+#define INCR_TX_DESC_INDEX(inx, offset) do {\
+ (inx) += (offset);\
+ if ((inx) >= (uint32_t)ETH_TX_DESC_CNT){\
+ (inx) = ((inx) - (uint32_t)ETH_TX_DESC_CNT);}\
+} while (0)
+
+/* Helper macros for RX descriptor handling */
+#define INCR_RX_DESC_INDEX(inx, offset) do {\
+ (inx) += (offset);\
+ if ((inx) >= (uint32_t)ETH_RX_DESC_CNT){\
+ (inx) = ((inx) - (uint32_t)ETH_RX_DESC_CNT);}\
+} while (0)
+/**
+ * @}
+ */
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup ETH_Private_Functions ETH Private Functions
+ * @{
+ */
+static void ETH_MAC_MDIO_ClkConfig(ETH_HandleTypeDef *heth);
+static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf);
+static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf);
+static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth);
+static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth);
+static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth);
+static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t ItMode);
+
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth);
+#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+/** @defgroup ETH_Exported_Functions ETH Exported Functions
+ * @{
+ */
+
+/** @defgroup ETH_Exported_Functions_Group1 Initialization and deinitialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to initialize and
+ deinitialize the ETH peripheral:
+
+ (+) User must Implement HAL_ETH_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO and NVIC ).
+
+ (+) Call the function HAL_ETH_Init() to configure the selected device with
+ the selected configuration:
+ (++) MAC address
+ (++) Media interface (MII or RMII)
+ (++) Rx DMA Descriptors Tab
+ (++) Tx DMA Descriptors Tab
+ (++) Length of Rx Buffers
+
+ (+) Call the function HAL_ETH_DescAssignMemory() to assign data buffers
+ for each Rx DMA Descriptor
+
+ (+) Call the function HAL_ETH_DeInit() to restore the default configuration
+ of the selected ETH peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the Ethernet peripheral registers.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth)
+{
+ uint32_t tickstart;
+
+ if(heth == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+
+ if(heth->gState == HAL_ETH_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ heth->Lock = HAL_UNLOCKED;
+
+ ETH_InitCallbacksToDefault(heth);
+
+ if(heth->MspInitCallback == NULL)
+ {
+ heth->MspInitCallback = HAL_ETH_MspInit;
+ }
+
+ /* Init the low level hardware */
+ heth->MspInitCallback(heth);
+ }
+
+#else
+
+ /* Check the ETH peripheral state */
+ if(heth->gState == HAL_ETH_STATE_RESET)
+ {
+ /* Init the low level hardware : GPIO, CLOCK, NVIC. */
+ HAL_ETH_MspInit(heth);
+ }
+#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */
+
+ heth->gState = HAL_ETH_STATE_BUSY;
+
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+
+ if(heth->Init.MediaInterface == HAL_ETH_MII_MODE)
+ {
+ HAL_SYSCFG_ETHInterfaceSelect(SYSCFG_ETH_MII);
+ }
+ else
+ {
+ HAL_SYSCFG_ETHInterfaceSelect(SYSCFG_ETH_RMII);
+ }
+
+ /* Ethernet Software reset */
+ /* Set the SWR bit: resets all MAC subsystem internal registers and logic */
+ /* After reset all the registers holds their respective reset values */
+ SET_BIT(heth->Instance->DMAMR, ETH_DMAMR_SWR);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait for software reset */
+ while (READ_BIT(heth->Instance->DMAMR, ETH_DMAMR_SWR) > 0U)
+ {
+ if(((HAL_GetTick() - tickstart ) > ETH_SWRESET_TIMEOUT))
+ {
+ /* Set Error Code */
+ heth->ErrorCode = HAL_ETH_ERROR_TIMEOUT;
+ /* Set State as Error */
+ heth->gState = HAL_ETH_STATE_ERROR;
+ /* Return Error */
+ return HAL_ERROR;
+ }
+ }
+
+ /*------------------ MDIO CSR Clock Range Configuration --------------------*/
+ ETH_MAC_MDIO_ClkConfig(heth);
+
+ /*------------------ MAC LPI 1US Tic Counter Configuration --------------------*/
+ WRITE_REG(heth->Instance->MAC1USTCR, (((uint32_t)HAL_RCC_GetHCLKFreq() / ETH_MAC_US_TICK) - 1U));
+
+ /*------------------ MAC, MTL and DMA default Configuration ----------------*/
+ ETH_MACDMAConfig(heth);
+
+ /* SET DSL to 64 bit */
+ MODIFY_REG(heth->Instance->DMACCR, ETH_DMACCR_DSL, ETH_DMACCR_DSL_64BIT);
+
+ /* Set Receive Buffers Length (must be a multiple of 4) */
+ if ((heth->Init.RxBuffLen % 0x4U) != 0x0U)
+ {
+ /* Set Error Code */
+ heth->ErrorCode = HAL_ETH_ERROR_PARAM;
+ /* Set State as Error */
+ heth->gState = HAL_ETH_STATE_ERROR;
+ /* Return Error */
+ return HAL_ERROR;
+ }
+ else
+ {
+ MODIFY_REG(heth->Instance->DMACRCR, ETH_DMACRCR_RBSZ, ((heth->Init.RxBuffLen) << 1));
+ }
+
+ /*------------------ DMA Tx Descriptors Configuration ----------------------*/
+ ETH_DMATxDescListInit(heth);
+
+ /*------------------ DMA Rx Descriptors Configuration ----------------------*/
+ ETH_DMARxDescListInit(heth);
+
+ /*--------------------- ETHERNET MAC Address Configuration ------------------*/
+ /* Set MAC addr bits 32 to 47 */
+ heth->Instance->MACA0HR = (((uint32_t)(heth->Init.MACAddr[5]) << 8) | (uint32_t)heth->Init.MACAddr[4]);
+ /* Set MAC addr bits 0 to 31 */
+ heth->Instance->MACA0LR = (((uint32_t)(heth->Init.MACAddr[3]) << 24) | ((uint32_t)(heth->Init.MACAddr[2]) << 16) |
+ ((uint32_t)(heth->Init.MACAddr[1]) << 8) | (uint32_t)heth->Init.MACAddr[0]);
+
+ heth->ErrorCode = HAL_ETH_ERROR_NONE;
+ heth->gState = HAL_ETH_STATE_READY;
+ heth->RxState = HAL_ETH_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the ETH peripheral.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth)
+{
+ /* Set the ETH peripheral state to BUSY */
+ heth->gState = HAL_ETH_STATE_BUSY;
+
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+
+ if(heth->MspDeInitCallback == NULL)
+ {
+ heth->MspDeInitCallback = HAL_ETH_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ heth->MspDeInitCallback(heth);
+#else
+
+ /* De-Init the low level hardware : GPIO, CLOCK, NVIC. */
+ HAL_ETH_MspDeInit(heth);
+
+#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */
+
+ /* Set ETH HAL state to Disabled */
+ heth->gState= HAL_ETH_STATE_RESET;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the ETH MSP.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+__weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(heth);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ETH_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes ETH MSP.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+__weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(heth);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ETH_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User ETH Callback
+ * To be used instead of the weak predefined callback
+ * @param heth eth handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_ETH_DMA_ERROR_CB_ID DMA Error Callback ID
+ * @arg @ref HAL_ETH_MAC_ERROR_CB_ID MAC Error Callback ID
+ * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID
+ * @arg @ref HAL_ETH_EEE_CB_ID EEE Callback ID
+ * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID
+ * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, pETH_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(heth);
+
+ if(heth->gState == HAL_ETH_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_ETH_TX_COMPLETE_CB_ID :
+ heth->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_ETH_RX_COMPLETE_CB_ID :
+ heth->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_ETH_DMA_ERROR_CB_ID :
+ heth->DMAErrorCallback = pCallback;
+ break;
+
+ case HAL_ETH_MAC_ERROR_CB_ID :
+ heth->MACErrorCallback = pCallback;
+ break;
+
+ case HAL_ETH_PMT_CB_ID :
+ heth->PMTCallback = pCallback;
+ break;
+
+ case HAL_ETH_EEE_CB_ID :
+ heth->EEECallback = pCallback;
+ break;
+
+ case HAL_ETH_WAKEUP_CB_ID :
+ heth->WakeUpCallback = pCallback;
+ break;
+
+ case HAL_ETH_MSPINIT_CB_ID :
+ heth->MspInitCallback = pCallback;
+ break;
+
+ case HAL_ETH_MSPDEINIT_CB_ID :
+ heth->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(heth->gState == HAL_ETH_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_ETH_MSPINIT_CB_ID :
+ heth->MspInitCallback = pCallback;
+ break;
+
+ case HAL_ETH_MSPDEINIT_CB_ID :
+ heth->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(heth);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an ETH Callback
+ * ETH callabck is redirected to the weak predefined callback
+ * @param heth eth handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_ETH_DMA_ERROR_CB_ID DMA Error Callback ID
+ * @arg @ref HAL_ETH_MAC_ERROR_CB_ID MAC Error Callback ID
+ * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID
+ * @arg @ref HAL_ETH_EEE_CB_ID EEE Callback ID
+ * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID
+ * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(heth);
+
+ if(heth->gState == HAL_ETH_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_ETH_TX_COMPLETE_CB_ID :
+ heth->TxCpltCallback = HAL_ETH_TxCpltCallback;
+ break;
+
+ case HAL_ETH_RX_COMPLETE_CB_ID :
+ heth->RxCpltCallback = HAL_ETH_RxCpltCallback;
+ break;
+
+ case HAL_ETH_DMA_ERROR_CB_ID :
+ heth->DMAErrorCallback = HAL_ETH_DMAErrorCallback;
+ break;
+
+ case HAL_ETH_MAC_ERROR_CB_ID :
+ heth->MACErrorCallback = HAL_ETH_MACErrorCallback;
+ break;
+
+ case HAL_ETH_PMT_CB_ID :
+ heth->PMTCallback = HAL_ETH_PMTCallback;
+ break;
+
+ case HAL_ETH_EEE_CB_ID :
+ heth->EEECallback = HAL_ETH_EEECallback;
+ break;
+
+ case HAL_ETH_WAKEUP_CB_ID :
+ heth->WakeUpCallback = HAL_ETH_WakeUpCallback;
+ break;
+
+ case HAL_ETH_MSPINIT_CB_ID :
+ heth->MspInitCallback = HAL_ETH_MspInit;
+ break;
+
+ case HAL_ETH_MSPDEINIT_CB_ID :
+ heth->MspDeInitCallback = HAL_ETH_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(heth->gState == HAL_ETH_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_ETH_MSPINIT_CB_ID :
+ heth->MspInitCallback = HAL_ETH_MspInit;
+ break;
+
+ case HAL_ETH_MSPDEINIT_CB_ID :
+ heth->MspDeInitCallback = HAL_ETH_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(heth);
+
+ return status;
+}
+#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
+
+/**
+ * @brief Assign memory buffers to a DMA Rx descriptor
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param Index : index of the DMA Rx descriptor
+ * this parameter can be a value from 0x0 to (ETH_RX_DESC_CNT -1)
+ * @param pBuffer1: address of buffer 1
+ * @param pBuffer2: address of buffer 2 if available
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_DescAssignMemory(ETH_HandleTypeDef *heth, uint32_t Index, uint8_t *pBuffer1, uint8_t *pBuffer2)
+{
+ ETH_DMADescTypeDef *dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[Index];
+
+ if((pBuffer1 == NULL) || (Index >= (uint32_t)ETH_RX_DESC_CNT))
+ {
+ /* Set Error Code */
+ heth->ErrorCode = HAL_ETH_ERROR_PARAM;
+ /* Return Error */
+ return HAL_ERROR;
+ }
+
+ /* write buffer address to RDES0 */
+ WRITE_REG(dmarxdesc->DESC0, (uint32_t)pBuffer1);
+ /* store buffer address */
+ WRITE_REG(dmarxdesc->BackupAddr0, (uint32_t)pBuffer1);
+ /* set buffer address valid bit to RDES3 */
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_BUF1V);
+
+ if(pBuffer2 != NULL)
+ {
+ /* write buffer 2 address to RDES1 */
+ WRITE_REG(dmarxdesc->DESC2, (uint32_t)pBuffer2);
+ /* store buffer 2 address */
+ WRITE_REG(dmarxdesc->BackupAddr1, (uint32_t)pBuffer2);
+ /* set buffer 2 address valid bit to RDES3 */
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_BUF2V);
+ }
+ /* set OWN bit to RDES3 */
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_OWN);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ETH_Exported_Functions_Group2 IO operation functions
+ * @brief ETH Transmit and Receive functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the ETH
+ data transfer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables Ethernet MAC and DMA reception and transmission
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth)
+{
+ if(heth->gState == HAL_ETH_STATE_READY)
+ {
+ heth->gState = HAL_ETH_STATE_BUSY;
+
+ /* Enable the MAC transmission */
+ SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE);
+
+ /* Enable the MAC reception */
+ SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE);
+
+ /* Set the Flush Transmit FIFO bit */
+ SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ);
+
+ /* Enable the DMA transmission */
+ SET_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST);
+
+ /* Enable the DMA reception */
+ SET_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR);
+
+ /* Clear Tx and Rx process stopped flags */
+ heth->Instance->DMACSR |= (ETH_DMACSR_TPS | ETH_DMACSR_RPS);
+
+ heth->gState = HAL_ETH_STATE_READY;
+ heth->RxState = HAL_ETH_STATE_BUSY_RX;
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enables Ethernet MAC and DMA reception/transmission in Interrupt mode
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth)
+{
+ uint32_t descindex = 0, counter;
+ ETH_DMADescTypeDef *dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descindex];
+
+ if(heth->gState == HAL_ETH_STATE_READY)
+ {
+ heth->gState = HAL_ETH_STATE_BUSY;
+
+ /* Set IOC bit to all Rx descriptors */
+ for(counter= 0; counter < (uint32_t)ETH_RX_DESC_CNT; counter++)
+ {
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_IOC);
+ INCR_RX_DESC_INDEX(descindex, 1U);
+ dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descindex];
+ }
+
+ /* save IT mode to ETH Handle */
+ heth->RxDescList.ItMode = 1U;
+
+ /* Enable the MAC transmission */
+ SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE);
+
+ /* Enable the MAC reception */
+ SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE);
+
+ /* Set the Flush Transmit FIFO bit */
+ SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ);
+
+ /* Enable the DMA transmission */
+ SET_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST);
+
+ /* Enable the DMA reception */
+ SET_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR);
+
+ /* Clear Tx and Rx process stopped flags */
+ heth->Instance->DMACSR |= (ETH_DMACSR_TPS | ETH_DMACSR_RPS);
+
+ heth->gState = HAL_ETH_STATE_READY;
+ heth->RxState = HAL_ETH_STATE_BUSY_RX;
+
+ /* Enable ETH DMA interrupts:
+ - Tx complete interrupt
+ - Rx complete interrupt
+ - Fatal bus interrupt
+ */
+ __HAL_ETH_DMA_ENABLE_IT(heth, (ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE |
+ ETH_DMACIER_FBEE | ETH_DMACIER_AIE));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Stop Ethernet MAC and DMA reception/transmission
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth)
+{
+ if(heth->gState != HAL_ETH_STATE_RESET)
+ {
+ /* Set the ETH peripheral state to BUSY */
+ heth->gState = HAL_ETH_STATE_BUSY;
+
+ /* Disable the DMA transmission */
+ CLEAR_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST);
+
+ /* Disable the DMA reception */
+ CLEAR_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR);
+
+ /* Disable the MAC reception */
+ CLEAR_BIT( heth->Instance->MACCR, ETH_MACCR_RE);
+
+ /* Set the Flush Transmit FIFO bit */
+ SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ);
+
+ /* Disable the MAC transmission */
+ CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE);
+
+ heth->gState = HAL_ETH_STATE_READY;
+ heth->RxState = HAL_ETH_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Stop Ethernet MAC and DMA reception/transmission in Interrupt mode
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth)
+{
+ ETH_DMADescTypeDef *dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[0];
+ uint32_t index;
+
+ if(heth->gState != HAL_ETH_STATE_RESET)
+ {
+ /* Set the ETH peripheral state to BUSY */
+ heth->gState = HAL_ETH_STATE_BUSY;
+
+ /* Disable intrrupts:
+ - Tx complete interrupt
+ - Rx complete interrupt */
+ __HAL_ETH_DMA_DISABLE_IT(heth, (ETH_DMA_NORMAL_IT | ETH_DMA_RX_IT | ETH_DMA_TX_IT));
+
+ /* Disable the DMA transmission */
+ CLEAR_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST);
+
+ /* Disable the DMA reception */
+ CLEAR_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR);
+
+ /* Disable the MAC reception */
+ CLEAR_BIT( heth->Instance->MACCR, ETH_MACCR_RE);
+
+ /* Set the Flush Transmit FIFO bit */
+ SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ);
+
+ /* Disable the MAC transmission */
+ CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE);
+
+ /* Clear IOC bit to all Rx descriptors */
+ for(index = 0; index < (uint32_t)ETH_RX_DESC_CNT; index++)
+ {
+ CLEAR_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_IOC);
+ }
+
+ heth->RxDescList.ItMode = 0U;
+
+ heth->gState = HAL_ETH_STATE_READY;
+ heth->RxState = HAL_ETH_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Sends an Ethernet Packet in polling mode.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pTxConfig: Hold the configuration of packet to be transmitted
+ * @param Timeout: timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ const ETH_DMADescTypeDef *dmatxdesc;
+
+ if(pTxConfig == NULL)
+ {
+ heth->ErrorCode |= HAL_ETH_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(heth->gState == HAL_ETH_STATE_READY)
+ {
+ /* Config DMA Tx descriptor by Tx Packet info */
+ if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 0) != HAL_ETH_ERROR_NONE)
+ {
+ /* Set the ETH error code */
+ heth->ErrorCode |= HAL_ETH_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+
+ dmatxdesc = (ETH_DMADescTypeDef *)(&heth->TxDescList)->TxDesc[heth->TxDescList.CurTxDesc];
+
+ /* Incr current tx desc index */
+ INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U);
+
+ /* Start transmission */
+ /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */
+ WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc]));
+
+ tickstart = HAL_GetTick();
+
+ /* Wait for data to be transmitted or timeout occured */
+ while((dmatxdesc->DESC3 & ETH_DMATXNDESCWBF_OWN) != (uint32_t)RESET)
+ {
+ if((heth->Instance->DMACSR & ETH_DMACSR_FBE) != (uint32_t)RESET)
+ {
+ heth->ErrorCode |= HAL_ETH_ERROR_DMA;
+ heth->DMAErrorCode = heth->Instance->DMACSR;
+ /* Set ETH HAL State to Ready */
+ heth->gState = HAL_ETH_STATE_ERROR;
+ /* Return function status */
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U))
+ {
+ heth->ErrorCode |= HAL_ETH_ERROR_TIMEOUT;
+ heth->gState = HAL_ETH_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Set ETH HAL State to Ready */
+ heth->gState = HAL_ETH_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Sends an Ethernet Packet in interrupt mode.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pTxConfig: Hold the configuration of packet to be transmitted
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig)
+{
+ if(pTxConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(heth->gState == HAL_ETH_STATE_READY)
+ {
+ /* Config DMA Tx descriptor by Tx Packet info */
+ if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 1) != HAL_ETH_ERROR_NONE)
+ {
+ heth->ErrorCode = HAL_ETH_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+
+ /* Incr current tx desc index */
+ INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U);
+
+ /* Start transmission */
+ /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */
+ WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc]));
+
+ return HAL_OK;
+
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Checks for received Packets.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval 1: A Packet is received
+ * 0: no Packet received
+ */
+uint8_t HAL_ETH_IsRxDataAvailable(ETH_HandleTypeDef *heth)
+{
+ ETH_RxDescListTypeDef *dmarxdesclist = &heth->RxDescList;
+ uint32_t descidx = dmarxdesclist->CurRxDesc;
+ ETH_DMADescTypeDef *dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+ uint32_t descscancnt = 0;
+ uint32_t appdesccnt = 0, firstappdescidx = 0;
+
+ if(dmarxdesclist->AppDescNbr != 0U)
+ {
+ /* data already received by not yet processed*/
+ return 0;
+ }
+
+ /* Check if descriptor is not owned by DMA */
+ while((READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_OWN) == (uint32_t)RESET) && (descscancnt < (uint32_t)ETH_RX_DESC_CNT))
+ {
+ descscancnt++;
+
+ /* Check if last descriptor */
+ if(READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_LD) != (uint32_t)RESET)
+ {
+ /* Increment the number of descriptors to be passed to the application */
+ appdesccnt += 1U;
+
+ if(appdesccnt == 1U)
+ {
+ WRITE_REG(firstappdescidx, descidx);
+ }
+
+ /* Increment current rx descriptor index */
+ INCR_RX_DESC_INDEX(descidx, 1U);
+
+ /* Check for Context descriptor */
+ /* Get current descriptor address */
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+
+ if(READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_OWN) == (uint32_t)RESET)
+ {
+ if(READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_CTXT) != (uint32_t)RESET)
+ {
+ /* Increment the number of descriptors to be passed to the application */
+ dmarxdesclist->AppContextDesc = 1;
+ /* Increment current rx descriptor index */
+ INCR_RX_DESC_INDEX(descidx, 1U);
+ }
+ }
+ /* Fill information to Rx descriptors list */
+ dmarxdesclist->CurRxDesc = descidx;
+ dmarxdesclist->FirstAppDesc = firstappdescidx;
+ dmarxdesclist->AppDescNbr = appdesccnt;
+
+ /* Return function status */
+ return 1;
+ }
+ /* Check if first descriptor */
+ else if(READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_FD) != (uint32_t)RESET)
+ {
+ WRITE_REG(firstappdescidx, descidx);
+ /* Increment the number of descriptors to be passed to the application */
+ appdesccnt = 1U;
+
+ /* Increment current rx descriptor index */
+ INCR_RX_DESC_INDEX(descidx, 1U);
+ /* Get current descriptor address */
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+ }
+ /* It should be an intermediate descriptor */
+ else
+ {
+ /* Increment the number of descriptors to be passed to the application */
+ appdesccnt += 1U;
+
+ /* Increment current rx descriptor index */
+ INCR_RX_DESC_INDEX(descidx, 1U);
+ /* Get current descriptor address */
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+ }
+ }
+
+ /* Build Descriptors if an incomplete Packet is received */
+ if(appdesccnt > 0U)
+ {
+ descidx = firstappdescidx;
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+
+ for(descscancnt = 0; descscancnt < appdesccnt; descscancnt++)
+ {
+ WRITE_REG(dmarxdesc->DESC0, dmarxdesc->BackupAddr0);
+ WRITE_REG(dmarxdesc->DESC3, ETH_DMARXNDESCRF_BUF1V);
+
+ if (READ_REG(dmarxdesc->BackupAddr1) != ((uint32_t)RESET))
+ {
+ WRITE_REG(dmarxdesc->DESC2, dmarxdesc->BackupAddr1);
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_BUF2V);
+ }
+
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_OWN);
+
+ if(dmarxdesclist->ItMode != ((uint32_t)RESET))
+ {
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_IOC);
+ }
+
+ /* Increment rx descriptor index */
+ INCR_RX_DESC_INDEX(descidx, 1U);
+ /* Get descriptor address */
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+ }
+ }
+
+ /* Fill information to Rx descriptors list: No received Packet */
+ dmarxdesclist->AppDescNbr = 0U;
+
+ return 0;
+}
+
+/**
+ * @brief This function gets the buffer address of last received Packet.
+ * @note Please insure to allocate the RxBuffer structure before calling this function
+ * how to use example:
+ * HAL_ETH_GetRxDataLength(heth, &Length);
+ * BuffersNbr = (Length / heth->Init.RxBuffLen) + 1;
+ * RxBuffer = (ETH_BufferTypeDef *)malloc(BuffersNbr * sizeof(ETH_BufferTypeDef));
+ * HAL_ETH_GetRxDataBuffer(heth, RxBuffer);
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param RxBuffer: Pointer to a ETH_BufferTypeDef structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_GetRxDataBuffer(ETH_HandleTypeDef *heth, ETH_BufferTypeDef *RxBuffer)
+{
+ ETH_RxDescListTypeDef *dmarxdesclist = &heth->RxDescList;
+ uint32_t descidx = dmarxdesclist->FirstAppDesc;
+ uint32_t index, accumulatedlen = 0, lastdesclen;
+ __IO const ETH_DMADescTypeDef *dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+ ETH_BufferTypeDef *rxbuff = RxBuffer;
+
+ if(rxbuff == NULL)
+ {
+ heth->ErrorCode = HAL_ETH_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(dmarxdesclist->AppDescNbr == 0U)
+ {
+ if(HAL_ETH_IsRxDataAvailable(heth) == 0U)
+ {
+ /* No data to be transferred to the application */
+ return HAL_ERROR;
+ }
+ else
+ {
+ descidx = dmarxdesclist->FirstAppDesc;
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+ }
+ }
+
+ /* Get intermediate descriptors buffers: in case of the Packet is splitted into multi descriptors */
+ for(index = 0; index < (dmarxdesclist->AppDescNbr - 1U); index++)
+ {
+ /* Get Address and length of the first buffer address */
+ rxbuff->buffer = (uint8_t *) dmarxdesc->BackupAddr0;
+ rxbuff->len = heth->Init.RxBuffLen;
+
+ /* Check if the second buffer address of this descriptor is valid */
+ if(dmarxdesc->BackupAddr1 != 0U)
+ {
+ /* Point to next buffer */
+ rxbuff = (struct __ETH_BufferTypeDef *)rxbuff->next;
+ /* Get Address and length of the second buffer address */
+ rxbuff->buffer = (uint8_t *) dmarxdesc->BackupAddr1;
+ rxbuff->len = heth->Init.RxBuffLen;
+ }
+ else
+ {
+ /* Nothing to do here */
+ }
+
+ /* get total length until this descriptor */
+ accumulatedlen = READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_PL);
+
+ /* Increment to next descriptor */
+ INCR_RX_DESC_INDEX(descidx, 1U);
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+
+ /* Point to next buffer */
+ rxbuff = (struct __ETH_BufferTypeDef *)rxbuff->next;
+ }
+
+ /* last descriptor data length */
+ lastdesclen = READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_PL) - accumulatedlen;
+
+ /* Get Address of the first buffer address */
+ rxbuff->buffer = (uint8_t *) dmarxdesc->BackupAddr0;
+
+ /* data is in only one buffer */
+ if(lastdesclen <= heth->Init.RxBuffLen)
+ {
+ rxbuff->len = lastdesclen;
+ }
+ /* data is in two buffers */
+ else if(dmarxdesc->BackupAddr1 != 0U)
+ {
+ /* Get the Length of the first buffer address */
+ rxbuff->len = heth->Init.RxBuffLen;
+ /* Point to next buffer */
+ rxbuff = (struct __ETH_BufferTypeDef *)rxbuff->next;
+ /* Get the Address the Length of the second buffer address */
+ rxbuff->buffer = (uint8_t *) dmarxdesc->BackupAddr1;
+ rxbuff->len = lastdesclen - (heth->Init.RxBuffLen);
+ }
+ else /* Buffer 2 not valid*/
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief This function gets the length of last received Packet.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param Length: parameter to hold Rx packet length
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_ETH_GetRxDataLength(ETH_HandleTypeDef *heth, uint32_t *Length)
+{
+ ETH_RxDescListTypeDef *dmarxdesclist = &heth->RxDescList;
+ uint32_t descidx = dmarxdesclist->FirstAppDesc;
+ __IO const ETH_DMADescTypeDef *dmarxdesc;
+
+ if(dmarxdesclist->AppDescNbr == 0U)
+ {
+ if(HAL_ETH_IsRxDataAvailable(heth) == 0U)
+ {
+ /* No data to be transferred to the application */
+ return HAL_ERROR;
+ }
+ }
+
+ /* Get index of last descriptor */
+ INCR_RX_DESC_INDEX(descidx, (dmarxdesclist->AppDescNbr - 1U));
+ /* Point to last descriptor */
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+
+ *Length = READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_PL);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the Rx data info (Packet type, VLAN tag, Filters status, ...)
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param RxPacketInfo: parameter to hold info of received buffer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_GetRxDataInfo(ETH_HandleTypeDef *heth, ETH_RxPacketInfo *RxPacketInfo)
+{
+ ETH_RxDescListTypeDef *dmarxdesclist = &heth->RxDescList;
+ uint32_t descidx = dmarxdesclist->FirstAppDesc;
+ __IO const ETH_DMADescTypeDef *dmarxdesc;
+
+ if(dmarxdesclist->AppDescNbr == 0U)
+ {
+ if(HAL_ETH_IsRxDataAvailable(heth) == 0U)
+ {
+ /* No data to be transferred to the application */
+ return HAL_ERROR;
+ }
+ }
+
+ /* Get index of last descriptor */
+ INCR_RX_DESC_INDEX(descidx, ((dmarxdesclist->AppDescNbr) - 1U));
+ /* Point to last descriptor */
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
+
+ if((dmarxdesc->DESC3 & ETH_DMARXNDESCWBF_ES) != (uint32_t)RESET)
+ {
+ RxPacketInfo->ErrorCode = READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_ERRORS_MASK);
+ }
+ else
+ {
+ if(READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_RS0V) != 0U)
+ {
+
+ if(READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_LT) == ETH_DMARXNDESCWBF_LT_DVLAN)
+ {
+ RxPacketInfo->VlanTag = READ_BIT(dmarxdesc->DESC0, ETH_DMARXNDESCWBF_OVT);
+ RxPacketInfo->InnerVlanTag = READ_BIT(dmarxdesc->DESC0, ETH_DMARXNDESCWBF_IVT) >> 16;
+ }
+ else
+ {
+ RxPacketInfo->VlanTag = READ_BIT(dmarxdesc->DESC0, ETH_DMARXNDESCWBF_OVT);
+ }
+ }
+
+ if(READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_RS1V) != 0U)
+ {
+ /* Get Payload type */
+ RxPacketInfo->PayloadType =READ_BIT( dmarxdesc->DESC1, ETH_DMARXNDESCWBF_PT);
+ /* Get Header type */
+ RxPacketInfo->HeaderType = READ_BIT(dmarxdesc->DESC1, (ETH_DMARXNDESCWBF_IPV4 | ETH_DMARXNDESCWBF_IPV6));
+ /* Get Checksum status */
+ RxPacketInfo->Checksum = READ_BIT(dmarxdesc->DESC1, (ETH_DMARXNDESCWBF_IPCE | ETH_DMARXNDESCWBF_IPCB | ETH_DMARXNDESCWBF_IPHE));
+ }
+
+ if(READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_RS2V) != 0U)
+ {
+ RxPacketInfo->MacFilterStatus = READ_BIT(dmarxdesc->DESC2, (ETH_DMARXNDESCWBF_HF | ETH_DMARXNDESCWBF_DAF | ETH_DMARXNDESCWBF_SAF | ETH_DMARXNDESCWBF_VF));
+ RxPacketInfo->L3FilterStatus = READ_BIT(dmarxdesc->DESC2, (ETH_DMARXNDESCWBF_L3FM | ETH_DMARXNDESCWBF_L3L4FM));
+ RxPacketInfo->L4FilterStatus = READ_BIT(dmarxdesc->DESC2, (ETH_DMARXNDESCWBF_L4FM | ETH_DMARXNDESCWBF_L3L4FM));
+ }
+ }
+
+ /* Get the segment count */
+ WRITE_REG(RxPacketInfo->SegmentCnt, dmarxdesclist->AppDescNbr);
+
+ return HAL_OK;
+}
+
+/**
+* @brief This function gives back Rx Desc of the last received Packet
+* to the DMA, so ETH DMA will be able to use these descriptors
+* to receive next Packets.
+* It should be called after processing the received Packet.
+* @param heth: pointer to a ETH_HandleTypeDef structure that contains
+* the configuration information for ETHERNET module
+* @retval HAL status.
+*/
+HAL_StatusTypeDef HAL_ETH_BuildRxDescriptors(ETH_HandleTypeDef *heth)
+{
+ ETH_RxDescListTypeDef *dmarxdesclist = &heth->RxDescList;
+ uint32_t descindex = dmarxdesclist->FirstAppDesc;
+ __IO ETH_DMADescTypeDef *dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descindex];
+ uint32_t totalappdescnbr = dmarxdesclist->AppDescNbr;
+ uint32_t descscan;
+
+ if(dmarxdesclist->AppDescNbr == 0U)
+ {
+ /* No Rx descriptors to build */
+ return HAL_ERROR;
+ }
+
+ if(dmarxdesclist->AppContextDesc != 0U)
+ {
+ /* A context descriptor is available */
+ totalappdescnbr += 1U;
+ }
+
+ for(descscan =0; descscan < totalappdescnbr; descscan++)
+ {
+ WRITE_REG(dmarxdesc->DESC0, dmarxdesc->BackupAddr0);
+ WRITE_REG(dmarxdesc->DESC3, ETH_DMARXNDESCRF_BUF1V);
+
+ if (READ_REG(dmarxdesc->BackupAddr1) != 0U)
+ {
+ WRITE_REG(dmarxdesc->DESC2, dmarxdesc->BackupAddr1);
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_BUF2V);
+ }
+
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_OWN);
+
+ if(dmarxdesclist->ItMode != 0U)
+ {
+ SET_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_IOC);
+ }
+
+ if(descscan < (dmarxdesclist->AppDescNbr - 1U))
+ {
+ /* Increment rx descriptor index */
+ INCR_RX_DESC_INDEX(descindex, 1U);
+ /* Get descriptor address */
+ dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descindex];
+ }
+ }
+
+ /* Set the Tail pointer address to the last rx descriptor hold by the app */
+ WRITE_REG(heth->Instance->DMACRDTPR, (uint32_t)dmarxdesc);
+
+ /* reset the Application desc number */
+ WRITE_REG(dmarxdesclist->AppDescNbr, 0);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief This function handles ETH interrupt request.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval HAL status
+ */
+void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth)
+{
+ /* Packet received */
+ if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMACSR_RI))
+ {
+ if(__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMACIER_RIE))
+ {
+
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+ /*Call registered Receive complete callback*/
+ heth->RxCpltCallback(heth);
+#else
+ /* Receive complete callback */
+ HAL_ETH_RxCpltCallback(heth);
+#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
+
+ /* Clear the Eth DMA Rx IT pending bits */
+ __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMACSR_RI | ETH_DMACSR_NIS);
+ }
+ }
+
+ /* Packet transmitted */
+ if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMACSR_TI))
+ {
+ if(__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMACIER_TIE))
+ {
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+ /*Call registered Transmit complete callback*/
+ heth->TxCpltCallback(heth);
+#else
+ /* Transfer complete callback */
+ HAL_ETH_TxCpltCallback(heth);
+#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
+
+ /* Clear the Eth DMA Tx IT pending bits */
+ __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMACSR_TI | ETH_DMACSR_NIS);
+ }
+ }
+
+
+ /* ETH DMA Error */
+ if(__HAL_ETH_DMA_GET_IT(heth, ETH_DMACSR_AIS))
+ {
+ if(__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMACIER_AIE))
+ {
+ heth->ErrorCode |= HAL_ETH_ERROR_DMA;
+
+ /* if fatal bus error occured */
+ if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMACSR_FBE))
+ {
+ /* Get DMA error code */
+ heth->DMAErrorCode = READ_BIT(heth->Instance->DMACSR, (ETH_DMACSR_FBE | ETH_DMACSR_TPS | ETH_DMACSR_RPS));
+
+ /* Disable all interrupts */
+ __HAL_ETH_DMA_DISABLE_IT(heth, ETH_DMACIER_NIE | ETH_DMACIER_AIE);
+
+ /* Set HAL state to ERROR */
+ heth->gState = HAL_ETH_STATE_ERROR;
+ }
+ else
+ {
+ /* Get DMA error status */
+ heth->DMAErrorCode = READ_BIT(heth->Instance->DMACSR, (ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT |
+ ETH_DMACSR_RBU | ETH_DMACSR_AIS));
+
+ /* Clear the interrupt summary flag */
+ __HAL_ETH_DMA_CLEAR_IT(heth, (ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT |
+ ETH_DMACSR_RBU | ETH_DMACSR_AIS));
+ }
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+ /* Call registered DMA Error callback*/
+ heth->DMAErrorCallback(heth);
+#else
+ /* Ethernet DMA Error callback */
+ HAL_ETH_DMAErrorCallback(heth);
+#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
+
+ }
+ }
+
+ /* ETH MAC Error IT */
+ if(__HAL_ETH_MAC_GET_IT(heth, (ETH_MACIER_RXSTSIE | ETH_MACIER_TXSTSIE)))
+ {
+ /* Get MAC Rx Tx status and clear Status register pending bit */
+ heth->MACErrorCode = READ_REG(heth->Instance->MACRXTXSR);
+
+ heth->gState = HAL_ETH_STATE_ERROR;
+
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+ /* Call registered MAC Error callback*/
+ heth->DMAErrorCallback(heth);
+#else
+ /* Ethernet MAC Error callback */
+ HAL_ETH_MACErrorCallback(heth);
+#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
+
+ heth->MACErrorCode = (uint32_t)(0x0U);
+ }
+
+ /* ETH PMT IT */
+ if(__HAL_ETH_MAC_GET_IT(heth, ETH_MAC_PMT_IT))
+ {
+ /* Get MAC Wake-up source and clear the status register pending bit */
+ heth->MACWakeUpEvent = READ_BIT(heth->Instance->MACPCSR, (ETH_MACPCSR_RWKPRCVD | ETH_MACPCSR_MGKPRCVD));
+
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+ /* Call registered PMT callback*/
+ heth->PMTCallback(heth);
+#else
+ /* Ethernet PMT callback */
+ HAL_ETH_PMTCallback(heth);
+#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
+
+ heth->MACWakeUpEvent = (uint32_t)(0x0U);
+ }
+
+ /* ETH EEE IT */
+ if(__HAL_ETH_MAC_GET_IT(heth, ETH_MAC_LPI_IT))
+ {
+ /* Get MAC LPI interrupt source and clear the status register pending bit */
+ heth->MACLPIEvent = READ_BIT(heth->Instance->MACPCSR, 0x0000000FU);
+
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+ /* Call registered EEE callback*/
+ heth->EEECallback(heth);
+#else
+ /* Ethernet EEE callback */
+ HAL_ETH_EEECallback(heth);
+#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
+
+ heth->MACLPIEvent = (uint32_t)(0x0U);
+ }
+
+#if defined(DUAL_CORE)
+ if (HAL_GetCurrentCPUID() == CM7_CPUID)
+ {
+ /* check ETH WAKEUP exti flag */
+ if(__HAL_ETH_WAKEUP_EXTI_GET_FLAG(ETH_WAKEUP_EXTI_LINE) != (uint32_t)RESET)
+ {
+ /* Clear ETH WAKEUP Exti pending bit */
+ __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE);
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+ /* Call registered WakeUp callback*/
+ heth->WakeUpCallback(heth);
+#else
+ /* ETH WAKEUP callback */
+ HAL_ETH_WakeUpCallback(heth);
+#endif
+ }
+ }
+ else
+ {
+ /* check ETH WAKEUP exti flag */
+ if(__HAL_ETH_WAKEUP_EXTID2_GET_FLAG(ETH_WAKEUP_EXTI_LINE) != (uint32_t)RESET)
+ {
+ /* Clear ETH WAKEUP Exti pending bit */
+ __HAL_ETH_WAKEUP_EXTID2_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE);
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+ /* Call registered WakeUp callback*/
+ heth->WakeUpCallback(heth);
+#else
+ /* ETH WAKEUP callback */
+ HAL_ETH_WakeUpCallback(heth);
+#endif
+ }
+ }
+#else
+ /* check ETH WAKEUP exti flag */
+ if(__HAL_ETH_WAKEUP_EXTI_GET_FLAG(ETH_WAKEUP_EXTI_LINE) != (uint32_t)RESET)
+ {
+ /* Clear ETH WAKEUP Exti pending bit */
+ __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE);
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+ /* Call registered WakeUp callback*/
+ heth->WakeUpCallback(heth);
+#else
+ /* ETH WAKEUP callback */
+ HAL_ETH_WakeUpCallback(heth);
+#endif
+ }
+#endif
+}
+
+/**
+ * @brief Tx Transfer completed callbacks.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+__weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(heth);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ETH_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callbacks.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+__weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(heth);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ETH_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Ethernet DMA transfer error callbacks
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+__weak void HAL_ETH_DMAErrorCallback(ETH_HandleTypeDef *heth)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(heth);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ETH_DMAErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+* @brief Ethernet MAC transfer error callbacks
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+__weak void HAL_ETH_MACErrorCallback(ETH_HandleTypeDef *heth)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(heth);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ETH_MACErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Ethernet Power Management module IT callback
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+__weak void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(heth);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ETH_PMTCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Energy Efficient Etherent IT callback
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+__weak void HAL_ETH_EEECallback(ETH_HandleTypeDef *heth)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(heth);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ETH_EEECallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief ETH WAKEUP interrupt callback
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+__weak void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(heth);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ETH_WakeUpCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Read a PHY register
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param PHYAddr: PHY port address, must be a value from 0 to 31
+ * @param PHYReg: PHY register address, must be a value from 0 to 31
+ * @param pRegValue: parameter to hold read value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, uint32_t *pRegValue)
+{
+ uint32_t tmpreg, tickstart;
+
+ /* Check for the Busy flag */
+ if(READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) != 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Get the MACMDIOAR value */
+ WRITE_REG(tmpreg, heth->Instance->MACMDIOAR);
+
+ /* Prepare the MDIO Address Register value
+ - Set the PHY device address
+ - Set the PHY register address
+ - Set the read mode
+ - Set the MII Busy bit */
+
+ MODIFY_REG(tmpreg, ETH_MACMDIOAR_PA, (PHYAddr <<21));
+ MODIFY_REG(tmpreg, ETH_MACMDIOAR_RDA, (PHYReg << 16));
+ MODIFY_REG(tmpreg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_RD);
+ SET_BIT(tmpreg, ETH_MACMDIOAR_MB);
+
+ /* Write the result value into the MDII Address register */
+ WRITE_REG(heth->Instance->MACMDIOAR, tmpreg);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait for the Busy flag */
+ while(READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) > 0U)
+ {
+ if(((HAL_GetTick() - tickstart ) > ETH_MDIO_BUS_TIMEOUT))
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ /* Get MACMIIDR value */
+ WRITE_REG(*pRegValue, (uint16_t)heth->Instance->MACMDIODR);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Writes to a PHY register.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param PHYAddr: PHY port address, must be a value from 0 to 31
+ * @param PHYReg: PHY register address, must be a value from 0 to 31
+ * @param RegValue: the value to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_WritePHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, uint32_t RegValue)
+{
+ uint32_t tmpreg, tickstart;
+
+ /* Check for the Busy flag */
+ if(READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) != 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Get the MACMDIOAR value */
+ WRITE_REG(tmpreg, heth->Instance->MACMDIOAR);
+
+ /* Prepare the MDIO Address Register value
+ - Set the PHY device address
+ - Set the PHY register address
+ - Set the write mode
+ - Set the MII Busy bit */
+
+ MODIFY_REG(tmpreg, ETH_MACMDIOAR_PA, (PHYAddr <<21));
+ MODIFY_REG(tmpreg, ETH_MACMDIOAR_RDA, (PHYReg << 16));
+ MODIFY_REG(tmpreg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_WR);
+ SET_BIT(tmpreg, ETH_MACMDIOAR_MB);
+
+
+ /* Give the value to the MII data register */
+ WRITE_REG(ETH->MACMDIODR, (uint16_t)RegValue);
+
+ /* Write the result value into the MII Address register */
+ WRITE_REG(ETH->MACMDIOAR, tmpreg);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait for the Busy flag */
+ while(READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) > 0U)
+ {
+ if(((HAL_GetTick() - tickstart ) > ETH_MDIO_BUS_TIMEOUT))
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ETH_Exported_Functions_Group3 Peripheral Control functions
+ * @brief ETH control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the ETH
+ peripheral.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Get the configuration of the MAC and MTL subsystems.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param macconf: pointer to a ETH_MACConfigTypeDef structure that will hold
+ * the configuration of the MAC.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_ETH_GetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf)
+{
+ if (macconf == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Get MAC parameters */
+ macconf->PreambleLength = READ_BIT(heth->Instance->MACCR, ETH_MACCR_PRELEN);
+ macconf->DeferralCheck = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DC)>> 4) > 0U) ? ENABLE : DISABLE;
+ macconf->BackOffLimit = READ_BIT(heth->Instance->MACCR, ETH_MACCR_BL);
+ macconf->RetryTransmission = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DR) >> 8) == 0U) ? ENABLE : DISABLE;
+ macconf->CarrierSenseDuringTransmit = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DCRS) >> 9) > 0U) ? ENABLE : DISABLE;
+ macconf->ReceiveOwn = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DO) >> 10) == 0U) ? ENABLE : DISABLE;
+ macconf->CarrierSenseBeforeTransmit = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_ECRSFD) >> 11) > 0U) ? ENABLE : DISABLE;
+ macconf->LoopbackMode = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_LM) >> 12) > 0U) ? ENABLE : DISABLE;
+ macconf->DuplexMode = READ_BIT(heth->Instance->MACCR, ETH_MACCR_DM);
+ macconf->Speed = READ_BIT(heth->Instance->MACCR, ETH_MACCR_FES);
+ macconf->JumboPacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_JE) >> 16) > 0U) ? ENABLE : DISABLE;
+ macconf->Jabber = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_JD) >>17) == 0U) ? ENABLE : DISABLE;
+ macconf->Watchdog = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_WD) >>19) == 0U) ? ENABLE : DISABLE;
+ macconf->AutomaticPadCRCStrip = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_ACS) >> 20) > 0U) ? ENABLE : DISABLE;
+ macconf->CRCStripTypePacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_CST) >> 21) > 0U) ? ENABLE : DISABLE;
+ macconf->Support2KPacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_S2KP) >> 22) > 0U) ? ENABLE : DISABLE;
+ macconf->GiantPacketSizeLimitControl = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_GPSLCE) >> 23) > 0U) ? ENABLE : DISABLE;
+ macconf->InterPacketGapVal = READ_BIT(heth->Instance->MACCR, ETH_MACCR_IPG);
+ macconf->ChecksumOffload = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_IPC) >> 27) > 0U) ? ENABLE : DISABLE;
+ macconf->SourceAddrControl = READ_BIT(heth->Instance->MACCR, ETH_MACCR_SARC);
+
+ macconf->GiantPacketSizeLimit = READ_BIT(heth->Instance->MACECR, ETH_MACECR_GPSL);
+ macconf->CRCCheckingRxPackets = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_DCRCC) >> 16) == 0U) ? ENABLE : DISABLE;
+ macconf->SlowProtocolDetect = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_SPEN) >> 17) > 0U) ? ENABLE : DISABLE;
+ macconf->UnicastSlowProtocolPacketDetect = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_USP) >> 18) > 0U) ? ENABLE : DISABLE;
+ macconf->ExtendedInterPacketGap = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_EIPGEN) >> 24) > 0U) ? ENABLE : DISABLE;
+ macconf->ExtendedInterPacketGapVal = READ_BIT(heth->Instance->MACECR, ETH_MACECR_EIPG) >> 25;
+
+
+ macconf->ProgrammableWatchdog = ((READ_BIT(heth->Instance->MACWTR, ETH_MACWTR_PWE) >> 8) > 0U) ? ENABLE : DISABLE;
+ macconf->WatchdogTimeout = READ_BIT(heth->Instance->MACWTR, ETH_MACWTR_WTO);
+
+ macconf->TransmitFlowControl = ((READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_TFE) >> 1) > 0U) ? ENABLE : DISABLE;
+ macconf->ZeroQuantaPause = ((READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_DZPQ) >> 7) == 0U) ? ENABLE : DISABLE;
+ macconf->PauseLowThreshold = READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_PLT);
+ macconf->PauseTime = (READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_PT) >> 16);
+
+
+ macconf->ReceiveFlowControl = (READ_BIT(heth->Instance->MACRFCR, ETH_MACRFCR_RFE) > 0U) ? ENABLE : DISABLE;
+ macconf->UnicastPausePacketDetect = ((READ_BIT(heth->Instance->MACRFCR, ETH_MACRFCR_UP) >> 1) > 0U) ? ENABLE : DISABLE;
+
+ macconf->TransmitQueueMode = READ_BIT(heth->Instance->MTLTQOMR, (ETH_MTLTQOMR_TTC | ETH_MTLTQOMR_TSF));
+
+ macconf->ReceiveQueueMode = READ_BIT(heth->Instance->MTLRQOMR, (ETH_MTLRQOMR_RTC | ETH_MTLRQOMR_RSF));
+ macconf->ForwardRxUndersizedGoodPacket = ((READ_BIT(heth->Instance->MTLRQOMR, ETH_MTLRQOMR_FUP) >> 3) > 0U) ? ENABLE : DISABLE;
+ macconf->ForwardRxErrorPacket = ((READ_BIT(heth->Instance->MTLRQOMR, ETH_MTLRQOMR_FEP) >> 4) > 0U) ? ENABLE : DISABLE;
+ macconf->DropTCPIPChecksumErrorPacket = ((READ_BIT(heth->Instance->MTLRQOMR, ETH_MTLRQOMR_DISTCPEF) >> 6) == 0U) ? ENABLE : DISABLE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the configuration of the DMA.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold
+ * the configuration of the ETH DMA.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_ETH_GetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf)
+{
+ if (dmaconf == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ dmaconf->AddressAlignedBeats = ((READ_BIT(heth->Instance->DMASBMR, ETH_DMASBMR_AAL) >> 12) > 0U) ? ENABLE : DISABLE;
+ dmaconf->BurstMode = READ_BIT(heth->Instance->DMASBMR, ETH_DMASBMR_FB | ETH_DMASBMR_MB);
+ dmaconf->RebuildINCRxBurst = ((READ_BIT(heth->Instance->DMASBMR, ETH_DMASBMR_RB)>> 15) > 0U) ? ENABLE : DISABLE;
+
+ dmaconf->DMAArbitration = READ_BIT(heth->Instance->DMAMR, (ETH_DMAMR_TXPR |ETH_DMAMR_PR | ETH_DMAMR_DA));
+
+ dmaconf->PBLx8Mode = ((READ_BIT(heth->Instance->DMACCR, ETH_DMACCR_8PBL)>> 16) > 0U) ? ENABLE : DISABLE;
+ dmaconf->MaximumSegmentSize = READ_BIT(heth->Instance->DMACCR, ETH_DMACCR_MSS);
+
+ dmaconf->FlushRxPacket = ((READ_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_RPF) >> 31) > 0U) ? ENABLE : DISABLE;
+ dmaconf->RxDMABurstLength = READ_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_RPBL);
+
+ dmaconf->SecondPacketOperate = ((READ_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_OSP) >> 4) > 0U) ? ENABLE : DISABLE;
+ dmaconf->TCPSegmentation = ((READ_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_TSE) >> 12) > 0U) ? ENABLE : DISABLE;
+ dmaconf->TxDMABurstLength = READ_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_TPBL);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the MAC configuration.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param macconf: pointer to a ETH_MACConfigTypeDef structure that contains
+ * the configuration of the MAC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf)
+{
+ if(macconf == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(heth->RxState == HAL_ETH_STATE_READY)
+ {
+ ETH_SetMACConfig(heth, macconf);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Set the ETH DMA configuration.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold
+ * the configuration of the ETH DMA.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf)
+{
+ if(dmaconf == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(heth->RxState == HAL_ETH_STATE_READY)
+ {
+ ETH_SetDMAConfig(heth, dmaconf);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configures the Clock range of ETH MDIO interface.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth)
+{
+ uint32_t tmpreg, hclk;
+
+ /* Get the ETHERNET MACMDIOAR value */
+ tmpreg = (heth->Instance)->MACMDIOAR;
+
+ /* Clear CSR Clock Range bits */
+ tmpreg &= ~ETH_MACMDIOAR_CR;
+
+ /* Get hclk frequency value */
+ hclk = HAL_RCC_GetHCLKFreq();
+
+ /* Set CR bits depending on hclk value */
+ if((hclk >= 20000000U)&&(hclk < 35000000U))
+ {
+ /* CSR Clock Range between 20-35 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV16;
+ }
+ else if((hclk >= 35000000U)&&(hclk < 60000000U))
+ {
+ /* CSR Clock Range between 35-60 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV26;
+ }
+ else if((hclk >= 60000000U)&&(hclk < 100000000U))
+ {
+ /* CSR Clock Range between 60-100 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV42;
+ }
+ else if((hclk >= 100000000U)&&(hclk < 150000000U))
+ {
+ /* CSR Clock Range between 100-150 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV62;
+ }
+ else /* (hclk >= 150000000)&&(hclk <= 200000000) */
+ {
+ /* CSR Clock Range between 150-200 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV102;
+ }
+
+ /* Configure the CSR Clock Range */
+ (heth->Instance)->MACMDIOAR = (uint32_t)tmpreg;
+}
+
+/**
+ * @brief Set the ETH MAC (L2) Filters configuration.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that contains
+ * the configuration of the ETH MAC filters.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig)
+{
+ uint32_t filterconfig;
+
+ if(pFilterConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ filterconfig = ((uint32_t)pFilterConfig->PromiscuousMode |
+ ((uint32_t)pFilterConfig->HashUnicast << 1) |
+ ((uint32_t)pFilterConfig->HashMulticast << 2) |
+ ((uint32_t)pFilterConfig->DestAddrInverseFiltering << 3) |
+ ((uint32_t)pFilterConfig->PassAllMulticast << 4) |
+ ((uint32_t)((pFilterConfig->BroadcastFilter == DISABLE) ? 1U : 0U) << 5) |
+ ((uint32_t)pFilterConfig->SrcAddrInverseFiltering << 8) |
+ ((uint32_t)pFilterConfig->SrcAddrFiltering << 9) |
+ ((uint32_t)pFilterConfig->HachOrPerfectFilter << 10) |
+ ((uint32_t)pFilterConfig->ReceiveAllMode << 31) |
+ pFilterConfig->ControlPacketsFilter);
+
+ MODIFY_REG(heth->Instance->MACPFR, ETH_MACPFR_MASK, filterconfig);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the ETH MAC (L2) Filters configuration.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that will hold
+ * the configuration of the ETH MAC filters.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig)
+{
+ if(pFilterConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ pFilterConfig->PromiscuousMode = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_PR)) > 0U) ? ENABLE : DISABLE;
+ pFilterConfig->HashUnicast = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_HUC) >> 1) > 0U) ? ENABLE : DISABLE;
+ pFilterConfig->HashMulticast = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_HMC) >> 2) > 0U) ? ENABLE : DISABLE;
+ pFilterConfig->DestAddrInverseFiltering = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_DAIF) >> 3) > 0U) ? ENABLE : DISABLE;
+ pFilterConfig->PassAllMulticast = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_PM) >> 4) > 0U) ? ENABLE : DISABLE;
+ pFilterConfig->BroadcastFilter = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_DBF) >> 5) == 0U) ? ENABLE : DISABLE;
+ pFilterConfig->ControlPacketsFilter = READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_PCF);
+ pFilterConfig->SrcAddrInverseFiltering = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_SAIF) >> 8) > 0U) ? ENABLE : DISABLE;
+ pFilterConfig->SrcAddrFiltering = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_SAF) >> 9) > 0U) ? ENABLE : DISABLE;
+ pFilterConfig->HachOrPerfectFilter = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_HPF) >> 10) > 0U) ? ENABLE : DISABLE;
+ pFilterConfig->ReceiveAllMode = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_RA) >> 31) > 0U) ? ENABLE : DISABLE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the source MAC Address to be matched.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param AddrNbr: The MAC address to configure
+ * This parameter must be a value of the following:
+ * ETH_MAC_ADDRESS1
+ * ETH_MAC_ADDRESS2
+ * ETH_MAC_ADDRESS3
+ * @param pMACAddr: Pointer to MAC address buffer data (6 bytes)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(ETH_HandleTypeDef *heth, uint32_t AddrNbr, uint8_t *pMACAddr)
+{
+ uint32_t macaddrhr, macaddrlr;
+
+ if(pMACAddr == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Get mac addr high reg offset */
+ macaddrhr = ((uint32_t)&(heth->Instance->MACA0HR) + AddrNbr);
+ /* Get mac addr low reg offset */
+ macaddrlr = ((uint32_t)&(heth->Instance->MACA0LR) + AddrNbr);
+
+ /* Set MAC addr bits 32 to 47 */
+ (*(__IO uint32_t *)macaddrhr) = (((uint32_t)(pMACAddr[5]) << 8) | (uint32_t)pMACAddr[4]);
+ /* Set MAC addr bits 0 to 31 */
+ (*(__IO uint32_t *)macaddrlr) = (((uint32_t)(pMACAddr[3]) << 24) | ((uint32_t)(pMACAddr[2]) << 16) |
+ ((uint32_t)(pMACAddr[1]) << 8) | (uint32_t)pMACAddr[0]);
+
+ /* Enable address and set source address bit */
+ (*(__IO uint32_t *)macaddrhr) |= (ETH_MACAHR_SA | ETH_MACAHR_AE);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the ETH Hash Table Value.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pHashTable: pointer to a table of two 32 bit values, that contains
+ * the 64 bits of the hash table.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable)
+{
+ if(pHashTable == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ heth->Instance->MACHT0R = pHashTable[0];
+ heth->Instance->MACHT1R = pHashTable[1];
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the VLAN Identifier for Rx packets
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param ComparisonBits: 12 or 16 bit comparison mode
+ must be a value of @ref ETH_VLAN_Tag_Comparison
+ * @param VLANIdentifier: VLAN Identifier value
+ * @retval None
+ */
+void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, uint32_t VLANIdentifier)
+{
+ if(ComparisonBits == ETH_VLANTAGCOMPARISON_16BIT)
+ {
+ MODIFY_REG(heth->Instance->MACVTR, ETH_MACVTR_VL , VLANIdentifier);
+ CLEAR_BIT(heth->Instance->MACVTR, ETH_MACVTR_ETV);
+ }
+ else
+ {
+ MODIFY_REG(heth->Instance->MACVTR, ETH_MACVTR_VL_VID , VLANIdentifier);
+ SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_ETV);
+ }
+}
+
+/**
+ * @brief Enters the Power down mode.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pPowerDownConfig: a pointer to ETH_PowerDownConfigTypeDef structure
+ * that contains the Power Down configration
+ * @retval None.
+ */
+void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, ETH_PowerDownConfigTypeDef *pPowerDownConfig)
+{
+ uint32_t powerdownconfig;
+
+ powerdownconfig = (((uint32_t)pPowerDownConfig->MagicPacket << 1) |
+ ((uint32_t)pPowerDownConfig->WakeUpPacket << 2) |
+ ((uint32_t)pPowerDownConfig->GlobalUnicast << 9) |
+ ((uint32_t)pPowerDownConfig->WakeUpForward << 10) |
+ ETH_MACPCSR_PWRDWN);
+
+ /* Enable PMT interrupt */
+ __HAL_ETH_MAC_ENABLE_IT(heth, ETH_MACIER_PMTIE);
+
+ MODIFY_REG(heth->Instance->MACPCSR, ETH_MACPCSR_MASK, powerdownconfig);
+}
+
+/**
+ * @brief Exits from the Power down mode.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None.
+ */
+void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth)
+{
+ /* clear wake up sources */
+ CLEAR_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_RWKPKTEN | ETH_MACPCSR_MGKPKTEN | ETH_MACPCSR_GLBLUCAST | ETH_MACPCSR_RWKPFE);
+
+ if(READ_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_PWRDWN) != 0U)
+ {
+ /* Exit power down mode */
+ CLEAR_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_PWRDWN);
+ }
+
+ /* Disable PMT interrupt */
+ __HAL_ETH_MAC_DISABLE_IT(heth, ETH_MACIER_PMTIE);
+}
+
+/**
+ * @brief Set the WakeUp filter.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pFilter: pointer to filter registers values
+ * @param Count: number of filter registers, must be from 1 to 8.
+ * @retval None.
+ */
+HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count)
+{
+ uint32_t regindex;
+
+ if(pFilter == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Reset Filter Pointer */
+ SET_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_RWKFILTRST);
+
+ /* Wake up packet filter config */
+ for(regindex = 0; regindex < Count; regindex++)
+ {
+ /* Write filter regs */
+ WRITE_REG(heth->Instance->MACRWKPFR, pFilter[regindex]);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ETH_Exported_Functions_Group4 Peripheral State and Errors functions
+ * @brief ETH State and Errors functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Errors functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to return the State of
+ ETH communication process, return Peripheral Errors occurred during communication
+ process
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the ETH state.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval HAL state
+ */
+HAL_ETH_StateTypeDef HAL_ETH_GetState(ETH_HandleTypeDef *heth)
+{
+ HAL_ETH_StateTypeDef ret;
+ HAL_ETH_StateTypeDef gstate = heth->gState;
+ HAL_ETH_StateTypeDef rxstate =heth->RxState;
+
+ ret = gstate;
+ ret |= rxstate;
+ return ret;
+}
+
+/**
+ * @brief Returns the ETH error code
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval ETH Error Code
+ */
+uint32_t HAL_ETH_GetError(ETH_HandleTypeDef *heth)
+{
+ return heth->ErrorCode;
+}
+
+/**
+ * @brief Returns the ETH DMA error code
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval ETH DMA Error Code
+ */
+uint32_t HAL_ETH_GetDMAError(ETH_HandleTypeDef *heth)
+{
+ return heth->DMAErrorCode;
+}
+
+/**
+ * @brief Returns the ETH MAC error code
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval ETH MAC Error Code
+ */
+uint32_t HAL_ETH_GetMACError(ETH_HandleTypeDef *heth)
+{
+ return heth->MACErrorCode;
+}
+
+/**
+ * @brief Returns the ETH MAC WakeUp event source
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval ETH MAC WakeUp event source
+ */
+uint32_t HAL_ETH_GetMACWakeUpSource(ETH_HandleTypeDef *heth)
+{
+ return heth->MACWakeUpEvent;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf)
+{
+ uint32_t macregval;
+
+ /*------------------------ MACCR Configuration --------------------*/
+ macregval =(macconf->InterPacketGapVal |
+ macconf->SourceAddrControl |
+ ((uint32_t)macconf->ChecksumOffload<< 27) |
+ ((uint32_t)macconf->GiantPacketSizeLimitControl << 23) |
+ ((uint32_t)macconf->Support2KPacket << 22) |
+ ((uint32_t)macconf->CRCStripTypePacket << 21) |
+ ((uint32_t)macconf->AutomaticPadCRCStrip << 20) |
+ ((uint32_t)((macconf->Watchdog == DISABLE) ? 1U : 0U) << 19) |
+ ((uint32_t)((macconf->Jabber == DISABLE) ? 1U : 0U) << 17) |
+ ((uint32_t)macconf->JumboPacket << 16) |
+ macconf->Speed |
+ macconf->DuplexMode |
+ ((uint32_t)macconf->LoopbackMode << 12) |
+ ((uint32_t)macconf->CarrierSenseBeforeTransmit << 11)|
+ ((uint32_t)((macconf->ReceiveOwn == DISABLE) ? 1U : 0U) << 10)|
+ ((uint32_t)macconf->CarrierSenseDuringTransmit << 9)|
+ ((uint32_t)((macconf->RetryTransmission == DISABLE) ? 1U : 0U) << 8)|
+ macconf->BackOffLimit |
+ ((uint32_t)macconf->DeferralCheck << 4)|
+ macconf->PreambleLength);
+
+ /* Write to MACCR */
+ MODIFY_REG(heth->Instance->MACCR, ETH_MACCR_MASK, macregval);
+
+ /*------------------------ MACECR Configuration --------------------*/
+ macregval = ((macconf->ExtendedInterPacketGapVal << 25)|
+ ((uint32_t)macconf->ExtendedInterPacketGap << 24)|
+ ((uint32_t)macconf->UnicastSlowProtocolPacketDetect << 18)|
+ ((uint32_t)macconf->SlowProtocolDetect << 17)|
+ ((uint32_t)((macconf->CRCCheckingRxPackets == DISABLE) ? 1U : 0U)<< 16) |
+ macconf->GiantPacketSizeLimit);
+
+ /* Write to MACECR */
+ MODIFY_REG(heth->Instance->MACECR, ETH_MACECR_MASK, macregval);
+
+ /*------------------------ MACWTR Configuration --------------------*/
+ macregval = (((uint32_t)macconf->ProgrammableWatchdog << 8) |
+ macconf->WatchdogTimeout);
+
+ /* Write to MACWTR */
+ MODIFY_REG(heth->Instance->MACWTR, ETH_MACWTR_MASK, macregval);
+
+ /*------------------------ MACTFCR Configuration --------------------*/
+ macregval = (((uint32_t)macconf->TransmitFlowControl << 1) |
+ macconf->PauseLowThreshold |
+ ((uint32_t)((macconf->ZeroQuantaPause == DISABLE) ? 1U : 0U)<< 7) |
+ (macconf->PauseTime << 16));
+
+ /* Write to MACTFCR */
+ MODIFY_REG(heth->Instance->MACTFCR, ETH_MACTFCR_MASK, macregval);
+
+ /*------------------------ MACRFCR Configuration --------------------*/
+ macregval = ((uint32_t)macconf->ReceiveFlowControl |
+ ((uint32_t)macconf->UnicastPausePacketDetect << 1));
+
+ /* Write to MACRFCR */
+ MODIFY_REG(heth->Instance->MACRFCR, ETH_MACRFCR_MASK, macregval);
+
+ /*------------------------ MTLTQOMR Configuration --------------------*/
+ /* Write to MTLTQOMR */
+ MODIFY_REG(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_MASK, macconf->TransmitQueueMode);
+
+ /*------------------------ MTLRQOMR Configuration --------------------*/
+ macregval = (macconf->ReceiveQueueMode |
+ ((uint32_t)((macconf->DropTCPIPChecksumErrorPacket == DISABLE) ? 1U : 0U) << 6) |
+ ((uint32_t)macconf->ForwardRxErrorPacket << 4) |
+ ((uint32_t)macconf->ForwardRxUndersizedGoodPacket << 3));
+
+ /* Write to MTLRQOMR */
+ MODIFY_REG(heth->Instance->MTLRQOMR, ETH_MTLRQOMR_MASK, macregval);
+}
+
+static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf)
+{
+ uint32_t dmaregval;
+
+ /*------------------------ DMAMR Configuration --------------------*/
+ MODIFY_REG(heth->Instance->DMAMR, ETH_DMAMR_MASK, dmaconf->DMAArbitration);
+
+ /*------------------------ DMASBMR Configuration --------------------*/
+ dmaregval = (((uint32_t)dmaconf->AddressAlignedBeats << 12) |
+ dmaconf->BurstMode |
+ ((uint32_t)dmaconf->RebuildINCRxBurst << 15));
+
+ MODIFY_REG(heth->Instance->DMASBMR, ETH_DMASBMR_MASK, dmaregval);
+
+ /*------------------------ DMACCR Configuration --------------------*/
+ dmaregval = (((uint32_t)dmaconf->PBLx8Mode << 16) |
+ dmaconf->MaximumSegmentSize);
+
+ MODIFY_REG(heth->Instance->DMACCR, ETH_DMACCR_MASK, dmaregval);
+
+ /*------------------------ DMACTCR Configuration --------------------*/
+ dmaregval = (dmaconf->TxDMABurstLength |
+ ((uint32_t)dmaconf->SecondPacketOperate << 4)|
+ ((uint32_t)dmaconf->TCPSegmentation << 12));
+
+ MODIFY_REG(heth->Instance->DMACTCR, ETH_DMACTCR_MASK, dmaregval);
+
+ /*------------------------ DMACRCR Configuration --------------------*/
+ dmaregval = (((uint32_t)dmaconf->FlushRxPacket << 31) |
+ dmaconf->RxDMABurstLength);
+
+ /* Write to DMACRCR */
+ MODIFY_REG(heth->Instance->DMACRCR, ETH_DMACRCR_MASK, dmaregval);
+}
+
+/**
+ * @brief Configures Ethernet MAC and DMA with default parameters.
+ * called by HAL_ETH_Init() API.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval HAL status
+ */
+static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth)
+{
+ ETH_MACConfigTypeDef macDefaultConf;
+ ETH_DMAConfigTypeDef dmaDefaultConf;
+
+ /*--------------- ETHERNET MAC registers default Configuration --------------*/
+ macDefaultConf.AutomaticPadCRCStrip = ENABLE;
+ macDefaultConf.BackOffLimit = ETH_BACKOFFLIMIT_10;
+ macDefaultConf.CarrierSenseBeforeTransmit = DISABLE;
+ macDefaultConf.CarrierSenseDuringTransmit = DISABLE;
+ macDefaultConf.ChecksumOffload = ENABLE;
+ macDefaultConf.CRCCheckingRxPackets = ENABLE;
+ macDefaultConf.CRCStripTypePacket = ENABLE;
+ macDefaultConf.DeferralCheck = DISABLE;
+ macDefaultConf.DropTCPIPChecksumErrorPacket = ENABLE;
+ macDefaultConf.DuplexMode = ETH_FULLDUPLEX_MODE;
+ macDefaultConf.ExtendedInterPacketGap = DISABLE;
+ macDefaultConf.ExtendedInterPacketGapVal = 0x0;
+ macDefaultConf.ForwardRxErrorPacket = DISABLE;
+ macDefaultConf.ForwardRxUndersizedGoodPacket = DISABLE;
+ macDefaultConf.GiantPacketSizeLimit = 0x618;
+ macDefaultConf.GiantPacketSizeLimitControl = DISABLE;
+ macDefaultConf.InterPacketGapVal = ETH_INTERPACKETGAP_96BIT;
+ macDefaultConf.Jabber = ENABLE;
+ macDefaultConf.JumboPacket = DISABLE;
+ macDefaultConf.LoopbackMode = DISABLE;
+ macDefaultConf.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS_4;
+ macDefaultConf.PauseTime = 0x0;
+ macDefaultConf.PreambleLength = ETH_PREAMBLELENGTH_7;
+ macDefaultConf.ProgrammableWatchdog = DISABLE;
+ macDefaultConf.ReceiveFlowControl = DISABLE;
+ macDefaultConf.ReceiveOwn = ENABLE;
+ macDefaultConf.ReceiveQueueMode = ETH_RECEIVESTOREFORWARD;
+ macDefaultConf.RetryTransmission = ENABLE;
+ macDefaultConf.SlowProtocolDetect = DISABLE;
+ macDefaultConf.SourceAddrControl = ETH_SOURCEADDRESS_REPLACE_ADDR0;
+ macDefaultConf.Speed = ETH_SPEED_100M;
+ macDefaultConf.Support2KPacket = DISABLE;
+ macDefaultConf.TransmitQueueMode = ETH_TRANSMITSTOREFORWARD;
+ macDefaultConf.TransmitFlowControl = DISABLE;
+ macDefaultConf.UnicastPausePacketDetect = DISABLE;
+ macDefaultConf.UnicastSlowProtocolPacketDetect = DISABLE;
+ macDefaultConf.Watchdog = ENABLE;
+ macDefaultConf.WatchdogTimeout = ETH_MACWTR_WTO_2KB;
+ macDefaultConf.ZeroQuantaPause = ENABLE;
+
+ /* MAC default configuration */
+ ETH_SetMACConfig(heth, &macDefaultConf);
+
+ /*--------------- ETHERNET DMA registers default Configuration --------------*/
+ dmaDefaultConf.AddressAlignedBeats = ENABLE;
+ dmaDefaultConf.BurstMode = ETH_BURSTLENGTH_FIXED;
+ dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_RX1_TX1;
+ dmaDefaultConf.FlushRxPacket = DISABLE;
+ dmaDefaultConf.PBLx8Mode = DISABLE;
+ dmaDefaultConf.RebuildINCRxBurst = DISABLE;
+ dmaDefaultConf.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
+ dmaDefaultConf.SecondPacketOperate = DISABLE;
+ dmaDefaultConf.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
+ dmaDefaultConf.TCPSegmentation = DISABLE;
+ dmaDefaultConf.MaximumSegmentSize = 536;
+
+ /* DMA default configuration */
+ ETH_SetDMAConfig(heth, &dmaDefaultConf);
+}
+
+/**
+ * @brief Configures the Clock range of SMI interface.
+ * called by HAL_ETH_Init() API.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+static void ETH_MAC_MDIO_ClkConfig(ETH_HandleTypeDef *heth)
+{
+ uint32_t tmpreg, hclk;
+
+ /* Get the ETHERNET MACMDIOAR value */
+ tmpreg = (heth->Instance)->MACMDIOAR;
+
+ /* Clear CSR Clock Range bits */
+ tmpreg &= ~ETH_MACMDIOAR_CR;
+
+ /* Get hclk frequency value */
+ hclk = HAL_RCC_GetHCLKFreq();
+
+ /* Set CR bits depending on hclk value */
+ if((hclk >= 20000000U)&&(hclk < 35000000U))
+ {
+ /* CSR Clock Range between 20-35 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV16;
+ }
+ else if((hclk >= 35000000U)&&(hclk < 60000000U))
+ {
+ /* CSR Clock Range between 35-60 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV26;
+ }
+ else if((hclk >= 60000000U)&&(hclk < 100000000U))
+ {
+ /* CSR Clock Range between 60-100 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV42;
+ }
+ else if((hclk >= 100000000U)&&(hclk < 150000000U))
+ {
+ /* CSR Clock Range between 100-150 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV62;
+ }
+ else /* (hclk >= 150000000)&&(hclk <= 200000000) */
+ {
+ /* CSR Clock Range between 150-200 MHz */
+ tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV102;
+ }
+
+ /* Configure the CSR Clock Range */
+ (heth->Instance)->MACMDIOAR = (uint32_t)tmpreg;
+}
+
+/**
+ * @brief Initializes the DMA Tx descriptors.
+ * called by HAL_ETH_Init() API.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth)
+{
+ ETH_DMADescTypeDef *dmatxdesc;
+ uint32_t i;
+
+ /* Fill each DMATxDesc descriptor with the right values */
+ for(i=0; i < (uint32_t)ETH_TX_DESC_CNT; i++)
+ {
+ dmatxdesc = heth->Init.TxDesc + i;
+
+ WRITE_REG(dmatxdesc->DESC0, 0x0);
+ WRITE_REG(dmatxdesc->DESC1, 0x0);
+ WRITE_REG(dmatxdesc->DESC2, 0x0);
+ WRITE_REG(dmatxdesc->DESC3, 0x0);
+
+ WRITE_REG(heth->TxDescList.TxDesc[i], (uint32_t)dmatxdesc);
+ }
+
+ heth->TxDescList.CurTxDesc = 0;
+
+ /* Set Transmit Descriptor Ring Length */
+ WRITE_REG(heth->Instance->DMACTDRLR, (ETH_TX_DESC_CNT -1));
+
+ /* Set Transmit Descriptor List Address */
+ WRITE_REG(heth->Instance->DMACTDLAR, (uint32_t) heth->Init.TxDesc);
+
+ /* Set Transmit Descriptor Tail pointer */
+ WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t) heth->Init.TxDesc);
+}
+
+/**
+ * @brief Initializes the DMA Rx descriptors in chain mode.
+ * called by HAL_ETH_Init() API.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth)
+{
+ ETH_DMADescTypeDef *dmarxdesc;
+ uint32_t i;
+
+ for(i = 0; i < (uint32_t)ETH_RX_DESC_CNT; i++)
+ {
+ dmarxdesc = heth->Init.RxDesc + i;
+
+ WRITE_REG(dmarxdesc->DESC0, 0x0);
+ WRITE_REG(dmarxdesc->DESC1, 0x0);
+ WRITE_REG(dmarxdesc->DESC2, 0x0);
+ WRITE_REG(dmarxdesc->DESC3, 0x0);
+ WRITE_REG(dmarxdesc->BackupAddr0, 0x0);
+ WRITE_REG(dmarxdesc->BackupAddr1, 0x0);
+
+ /* Set Rx descritors adresses */
+ WRITE_REG(heth->RxDescList.RxDesc[i], (uint32_t)dmarxdesc);
+ }
+
+ WRITE_REG(heth->RxDescList.CurRxDesc, 0);
+ WRITE_REG(heth->RxDescList.FirstAppDesc, 0);
+ WRITE_REG(heth->RxDescList.AppDescNbr, 0);
+ WRITE_REG(heth->RxDescList.ItMode, 0);
+ WRITE_REG(heth->RxDescList.AppContextDesc, 0);
+
+ /* Set Receive Descriptor Ring Length */
+ WRITE_REG(heth->Instance->DMACRDRLR, ((uint32_t)(ETH_RX_DESC_CNT - 1)));
+
+ /* Set Receive Descriptor List Address */
+ WRITE_REG(heth->Instance->DMACRDLAR, (uint32_t) heth->Init.RxDesc);
+
+ /* Set Receive Descriptor Tail pointer Address */
+ WRITE_REG(heth->Instance->DMACRDTPR, ((uint32_t)(heth->Init.RxDesc + (((uint32_t)(ETH_RX_DESC_CNT - 1))*sizeof(ETH_DMADescTypeDef)))));
+}
+
+/**
+ * @brief Prepare Tx DMA descriptor before transmission.
+ * called by HAL_ETH_Transmit_IT and HAL_ETH_Transmit_IT() API.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pTxConfig: Tx packet configuration
+ * @param ItMode: Enable or disable Tx EOT interrept
+ * @retval Status
+ */
+static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t ItMode)
+{
+ ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList;
+ uint32_t descidx = dmatxdesclist->CurTxDesc;
+ uint32_t firstdescidx = dmatxdesclist->CurTxDesc;
+ uint32_t descnbr = 0, idx;
+ ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
+
+ ETH_BufferTypeDef *txbuffer = pTxConfig->TxBuffer;
+
+ /* Current Tx Descriptor Owned by DMA: cannot be used by the application */
+ if(READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCWBF_OWN) == ETH_DMATXNDESCWBF_OWN)
+ {
+ return HAL_ETH_ERROR_BUSY;
+ }
+
+ /***************************************************************************/
+ /***************** Context descriptor configuration (Optional) **********/
+ /***************************************************************************/
+ /* If VLAN tag is enabled for this packet */
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != 0U)
+ {
+ /* Set vlan tag value */
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXCDESC_VT, pTxConfig->VlanTag);
+ /* Set vlan tag valid bit */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_VLTV);
+ /* Set the descriptor as the vlan input source */
+ SET_BIT(heth->Instance->MACVIR, ETH_MACVIR_VLTI);
+
+ /* if inner VLAN is enabled */
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_INNERVLANTAG) != 0U)
+ {
+ /* Set inner vlan tag value */
+ MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXCDESC_IVT, (pTxConfig->InnerVlanTag << 16));
+ /* Set inner vlan tag valid bit */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_IVLTV);
+
+ /* Set Vlan Tag control */
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXCDESC_IVTIR, pTxConfig->InnerVlanCtrl);
+
+ /* Set the descriptor as the inner vlan input source */
+ SET_BIT(heth->Instance->MACIVIR, ETH_MACIVIR_VLTI);
+ /* Enable double VLAN processing */
+ SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_EDVLP);
+ }
+ }
+
+ /* if tcp segementation is enabled for this packet */
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != 0U)
+ {
+ /* Set MSS value */
+ MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXCDESC_MSS, pTxConfig->MaxSegmentSize);
+ /* Set MSS valid bit */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_TCMSSV);
+ }
+
+ if((READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != 0U)|| (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != 0U))
+ {
+ /* Set as context descriptor */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_CTXT);
+ /* Set own bit */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_OWN);
+ /* Increment current tx descriptor index */
+ INCR_TX_DESC_INDEX(descidx, 1U);
+ /* Get current descriptor address */
+ dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
+
+ descnbr += 1U;
+
+ /* Current Tx Descriptor Owned by DMA: cannot be used by the application */
+ if(READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCWBF_OWN) == ETH_DMATXNDESCWBF_OWN)
+ {
+ dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[firstdescidx];
+ /* Clear own bit */
+ CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_OWN);
+
+ return HAL_ETH_ERROR_BUSY;
+ }
+ }
+
+ /***************************************************************************/
+ /***************** Normal descriptors configuration *****************/
+ /***************************************************************************/
+
+ descnbr += 1U;
+
+ /* Set header or buffer 1 address */
+ WRITE_REG(dmatxdesc->DESC0, (uint32_t)txbuffer->buffer);
+ /* Set header or buffer 1 Length */
+ MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B1L, txbuffer->len);
+
+ if(txbuffer->next != NULL)
+ {
+ txbuffer = txbuffer->next;
+ /* Set buffer 2 address */
+ WRITE_REG(dmatxdesc->DESC1, (uint32_t)txbuffer->buffer);
+ /* Set buffer 2 Length */
+ MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, (txbuffer->len << 16));
+ }
+ else
+ {
+ WRITE_REG(dmatxdesc->DESC1, 0x0);
+ /* Set buffer 2 Length */
+ MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, 0x0U);
+ }
+
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != 0U)
+ {
+ /* Set TCP Header length */
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_THL, (pTxConfig->TCPHeaderLen << 19));
+ /* Set TCP payload length */
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TPL, pTxConfig->PayloadLen);
+ /* Set TCP Segmentation Enabled bit */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TSE);
+ }
+ else
+ {
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FL, pTxConfig->Length);
+
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != 0U)
+ {
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CIC, pTxConfig->ChecksumCtrl);
+ }
+
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CRCPAD) != 0U)
+ {
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CPC, pTxConfig->CRCPadCtrl);
+ }
+ }
+
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != 0U)
+ {
+ /* Set Vlan Tag control */
+ MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_VTIR, pTxConfig->VlanCtrl);
+ }
+
+ /* Mark it as First Descriptor */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FD);
+ /* Mark it as NORMAL descriptor */
+ CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CTXT);
+ /* set OWN bit of FIRST descriptor */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN);
+
+ /* If source address insertion/replacement is enabled for this packet */
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_SAIC) != 0U)
+ {
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_SAIC, pTxConfig->SrcAddrCtrl);
+ }
+
+ /* only if the packet is splitted into more than one descriptors > 1 */
+ while (txbuffer->next != NULL)
+ {
+ /* Clear the LD bit of previous descriptor */
+ CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_LD);
+ /* Increment current tx descriptor index */
+ INCR_TX_DESC_INDEX(descidx, 1U);
+ /* Get current descriptor address */
+ dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
+
+ /* Clear the FD bit of new Descriptor */
+ CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FD);
+
+ /* Current Tx Descriptor Owned by DMA: cannot be used by the application */
+ if(READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN) == ETH_DMATXNDESCRF_OWN)
+ {
+ descidx = firstdescidx;
+ dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
+
+ /* clear previous desc own bit */
+ for(idx = 0; idx < descnbr; idx ++)
+ {
+ CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN);
+
+ /* Increment current tx descriptor index */
+ INCR_TX_DESC_INDEX(descidx, 1U);
+ /* Get current descriptor address */
+ dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx];
+ }
+
+ return HAL_ETH_ERROR_BUSY;
+ }
+
+ descnbr += 1U;
+
+ /* Get the next Tx buffer in the list */
+ txbuffer = (struct __ETH_BufferTypeDef *)txbuffer->next;
+
+ /* Set header or buffer 1 address */
+ WRITE_REG(dmatxdesc->DESC0, (uint32_t)txbuffer->buffer);
+ /* Set header or buffer 1 Length */
+ MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B1L, txbuffer->len);
+
+ if (txbuffer->next != NULL)
+ {
+ /* Get the next Tx buffer in the list */
+ txbuffer = (struct __ETH_BufferTypeDef *)txbuffer->next;
+ /* Set buffer 2 address */
+ WRITE_REG(dmatxdesc->DESC1, (uint32_t)txbuffer->buffer);
+ /* Set buffer 2 Length */
+ MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, (txbuffer->len << 16));
+ }
+ else
+ {
+ WRITE_REG(dmatxdesc->DESC1, 0x0);
+ /* Set buffer 2 Length */
+ MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, 0x0U);
+ }
+
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != 0U)
+ {
+ /* Set TCP payload length */
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TPL, pTxConfig->PayloadLen);
+ /* Set TCP Segmentation Enabled bit */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TSE);
+ }
+ else
+ {
+ /* Set the packet length */
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FL, pTxConfig->Length);
+
+ if(READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != 0U)
+ {
+ /* Checksum Insertion Control */
+ MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CIC, pTxConfig->ChecksumCtrl);
+ }
+ }
+
+ /* Set Own bit */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN);
+ /* Mark it as NORMAL descriptor */
+ CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CTXT);
+ }
+
+ if(ItMode != ((uint32_t)RESET))
+ {
+ /* Set Interrupt on completition bit */
+ SET_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_IOC);
+ }
+ else
+ {
+ /* Clear Interrupt on completition bit */
+ CLEAR_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_IOC);
+ }
+
+ /* Mark it as LAST descriptor */
+ SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_LD);
+
+ dmatxdesclist->CurTxDesc = descidx;
+
+ /* Return function status */
+ return HAL_ETH_ERROR_NONE;
+}
+
+#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
+static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth)
+{
+ /* Init the ETH Callback settings */
+ heth->TxCpltCallback = HAL_ETH_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ heth->RxCpltCallback = HAL_ETH_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ heth->DMAErrorCallback = HAL_ETH_DMAErrorCallback; /* Legacy weak DMAErrorCallback */
+ heth->MACErrorCallback = HAL_ETH_MACErrorCallback; /* Legacy weak MACErrorCallback */
+ heth->PMTCallback = HAL_ETH_PMTCallback; /* Legacy weak PMTCallback */
+ heth->EEECallback = HAL_ETH_EEECallback; /* Legacy weak EEECallback */
+ heth->WakeUpCallback = HAL_ETH_WakeUpCallback; /* Legacy weak WakeUpCallback */
+}
+#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
+
+
+/**
+ * @}
+ */
+
+#endif /* ETH */
+
+#endif /* HAL_ETH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_eth_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_eth_ex.c
new file mode 100644
index 0000000000..894443db6d
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_eth_ex.c
@@ -0,0 +1,559 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_eth_ex.c
+ * @author MCD Application Team
+ * @brief ETH HAL Extended module driver.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_ETH_MODULE_ENABLED
+
+#if defined(ETH)
+
+/** @defgroup ETHEx ETHEx
+ * @brief ETH HAL Extended module driver
+ * @{
+ */
+
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup ETHEx_Private_Constants ETHEx Private Constants
+ * @{
+ */
+#define ETH_MACL4CR_MASK (ETH_MACL3L4CR_L4PEN | ETH_MACL3L4CR_L4SPM | \
+ ETH_MACL3L4CR_L4SPIM | ETH_MACL3L4CR_L4DPM | \
+ ETH_MACL3L4CR_L4DPIM)
+
+#define ETH_MACL3CR_MASK (ETH_MACL3L4CR_L3PEN | ETH_MACL3L4CR_L3SAM | \
+ ETH_MACL3L4CR_L3SAIM | ETH_MACL3L4CR_L3DAM | \
+ ETH_MACL3L4CR_L3DAIM | ETH_MACL3L4CR_L3HSBM | \
+ ETH_MACL3L4CR_L3HDBM)
+
+#define ETH_MACRXVLAN_MASK (ETH_MACVTR_EIVLRXS | ETH_MACVTR_EIVLS | \
+ ETH_MACVTR_ERIVLT | ETH_MACVTR_EDVLP | \
+ ETH_MACVTR_VTHM | ETH_MACVTR_EVLRXS | \
+ ETH_MACVTR_EVLS | ETH_MACVTR_DOVLTC | \
+ ETH_MACVTR_ERSVLM | ETH_MACVTR_ESVL | \
+ ETH_MACVTR_VTIM | ETH_MACVTR_ETV)
+
+#define ETH_MACTXVLAN_MASK (ETH_MACVIR_VLTI | ETH_MACVIR_CSVL | \
+ ETH_MACVIR_VLP | ETH_MACVIR_VLC)
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions ---------------------------------------------------------*/
+/** @defgroup ETHEx_Exported_Functions ETH Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup ETHEx_Exported_Functions_Group1 Extended features functions
+ * @brief Extended features functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure ARP offload module
+ (+) Configure L3 and L4 filters
+ (+) Configure Extended VLAN features
+ (+) Configure Energy Efficient Ethernet module
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables ARP Offload.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+void HAL_ETHEx_EnableARPOffload(ETH_HandleTypeDef *heth)
+{
+ SET_BIT(heth->Instance->MACCR, ETH_MACCR_ARP);
+}
+
+/**
+ * @brief Disables ARP Offload.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+void HAL_ETHEx_DisableARPOffload(ETH_HandleTypeDef *heth)
+{
+ CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_ARP);
+}
+
+/**
+ * @brief Set the ARP Match IP address
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param IpAddress: IP Address to be matched for incoming ARP requests
+ * @retval None
+ */
+void HAL_ETHEx_SetARPAddressMatch(ETH_HandleTypeDef *heth, uint32_t IpAddress)
+{
+ WRITE_REG(heth->Instance->MACARPAR, IpAddress);
+}
+
+/**
+ * @brief Configures the L4 Filter, this function allow to:
+ * set the layer 4 protocol to be matched (TCP or UDP)
+ * enable/disable L4 source/destination port perfect/inverse match.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param Filter: L4 filter to configured, this parameter must be one of the following
+ * ETH_L4_FILTER_0
+ * ETH_L4_FILTER_1
+ * @param pL4FilterConfig: pointer to a ETH_L4FilterConfigTypeDef structure
+ * that contains L4 filter configuration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETHEx_SetL4FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter , ETH_L4FilterConfigTypeDef *pL4FilterConfig)
+{
+ __IO uint32_t *configreg = ((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter));
+
+ if(pL4FilterConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Write configuration to (MACL3L4C0R + filter )register */
+ MODIFY_REG(*configreg, ETH_MACL4CR_MASK ,(pL4FilterConfig->Protocol |
+ pL4FilterConfig->SrcPortFilterMatch |
+ pL4FilterConfig->DestPortFilterMatch));
+
+ configreg = ((__IO uint32_t *)(&(heth->Instance->MACL4A0R) + Filter));
+
+ /* Write configuration to (MACL4A0R + filter )register */
+ MODIFY_REG(*configreg, (ETH_MACL4AR_L4DP | ETH_MACL4AR_L4SP) , (pL4FilterConfig->SourcePort |
+ (pL4FilterConfig->DestinationPort << 16)));
+
+ /* Enable L4 filter */
+ SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the L4 Filter, this function allow to:
+ * set the layer 4 protocol to be matched (TCP or UDP)
+ * enable/disable L4 source/destination port perfect/inverse match.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param Filter: L4 filter to configured, this parameter must be one of the following
+ * ETH_L4_FILTER_0
+ * ETH_L4_FILTER_1
+ * @param pL4FilterConfig: pointer to a ETH_L4FilterConfigTypeDef structure
+ * that contains L4 filter configuration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETHEx_GetL4FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, ETH_L4FilterConfigTypeDef *pL4FilterConfig)
+{
+ if(pL4FilterConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Get configuration to (MACL3L4C0R + filter )register */
+ pL4FilterConfig->Protocol = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), ETH_MACL3L4CR_L4PEN);
+ pL4FilterConfig->DestPortFilterMatch = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), (ETH_MACL3L4CR_L4DPM | ETH_MACL3L4CR_L4DPIM));
+ pL4FilterConfig->SrcPortFilterMatch = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), (ETH_MACL3L4CR_L4SPM | ETH_MACL3L4CR_L4SPIM));
+
+ /* Get configuration to (MACL3L4C0R + filter )register */
+ pL4FilterConfig->DestinationPort = (READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL4A0R) + Filter)), ETH_MACL4AR_L4DP) >> 16);
+ pL4FilterConfig->SourcePort = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL4A0R) + Filter)), ETH_MACL4AR_L4SP);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the L3 Filter, this function allow to:
+ * set the layer 3 protocol to be matched (IPv4 or IPv6)
+ * enable/disable L3 source/destination port perfect/inverse match.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param Filter: L3 filter to configured, this parameter must be one of the following
+ * ETH_L3_FILTER_0
+ * ETH_L3_FILTER_1
+ * @param pL3FilterConfig: pointer to a ETH_L3FilterConfigTypeDef structure
+ * that contains L3 filter configuration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETHEx_SetL3FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, ETH_L3FilterConfigTypeDef *pL3FilterConfig)
+{
+ __IO uint32_t *configreg = ((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter));
+
+ if(pL3FilterConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Write configuration to (MACL3L4C0R + filter )register */
+ MODIFY_REG(*configreg, ETH_MACL3CR_MASK, (pL3FilterConfig->Protocol |
+ pL3FilterConfig->SrcAddrFilterMatch |
+ pL3FilterConfig->DestAddrFilterMatch |
+ (pL3FilterConfig->SrcAddrHigherBitsMatch << 6) |
+ (pL3FilterConfig->DestAddrHigherBitsMatch << 11)));
+
+ /* Check if IPv6 protocol is selected */
+ if(pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH)
+ {
+ /* Set the IPv6 address match */
+ /* Set Bits[31:0] of 128-bit IP addr */
+ *((__IO uint32_t *)(&(heth->Instance->MACL3A0R0R) + Filter)) = pL3FilterConfig->Ip6Addr[0];
+ /* Set Bits[63:32] of 128-bit IP addr */
+ *((__IO uint32_t *)(&(heth->Instance->MACL3A1R0R) + Filter)) = pL3FilterConfig->Ip6Addr[1];
+ /* update Bits[95:64] of 128-bit IP addr */
+ *((__IO uint32_t *)(&(heth->Instance->MACL3A2R0R) + Filter)) = pL3FilterConfig->Ip6Addr[2];
+ /* update Bits[127:96] of 128-bit IP addr */
+ *((__IO uint32_t *)(&(heth->Instance->MACL3A3R0R) + Filter)) = pL3FilterConfig->Ip6Addr[3];
+ }
+ else /* IPv4 protocol is selected */
+ {
+ /* Set the IPv4 source address match */
+ *((__IO uint32_t *)(&(heth->Instance->MACL3A0R0R) + Filter)) = pL3FilterConfig->Ip4SrcAddr;
+ /* Set the IPv4 destination address match */
+ *((__IO uint32_t *)(&(heth->Instance->MACL3A1R0R) + Filter)) = pL3FilterConfig->Ip4DestAddr;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the L3 Filter, this function allow to:
+ * set the layer 3 protocol to be matched (IPv4 or IPv6)
+ * enable/disable L3 source/destination port perfect/inverse match.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param Filter: L3 filter to configured, this parameter must be one of the following
+ * ETH_L3_FILTER_0
+ * ETH_L3_FILTER_1
+ * @param pL3FilterConfig: pointer to a ETH_L3FilterConfigTypeDef structure
+ * that will contain the L3 filter configuration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETHEx_GetL3FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, ETH_L3FilterConfigTypeDef *pL3FilterConfig)
+{
+ if(pL3FilterConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ pL3FilterConfig->Protocol = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), ETH_MACL3L4CR_L3PEN);
+ pL3FilterConfig->SrcAddrFilterMatch = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), (ETH_MACL3L4CR_L3SAM | ETH_MACL3L4CR_L3SAIM));
+ pL3FilterConfig->DestAddrFilterMatch = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), (ETH_MACL3L4CR_L3DAM | ETH_MACL3L4CR_L3DAIM));
+ pL3FilterConfig->SrcAddrHigherBitsMatch = (READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), ETH_MACL3L4CR_L3HSBM) >> 6);
+ pL3FilterConfig->DestAddrHigherBitsMatch = (READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), ETH_MACL3L4CR_L3HDBM) >> 11);
+
+ if(pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH)
+ {
+ pL3FilterConfig->Ip6Addr[0] = *((__IO uint32_t *)(&(heth->Instance->MACL3A0R0R) + Filter));
+ pL3FilterConfig->Ip6Addr[1] = *((__IO uint32_t *)(&(heth->Instance->MACL3A1R0R) + Filter));
+ pL3FilterConfig->Ip6Addr[2] = *((__IO uint32_t *)(&(heth->Instance->MACL3A2R0R) + Filter));
+ pL3FilterConfig->Ip6Addr[3] = *((__IO uint32_t *)(&(heth->Instance->MACL3A3R0R) + Filter));
+ }
+ else
+ {
+ pL3FilterConfig->Ip4SrcAddr = *((__IO uint32_t *)(&(heth->Instance->MACL3A0R0R) + Filter));
+ pL3FilterConfig->Ip4DestAddr = *((__IO uint32_t *)(&(heth->Instance->MACL3A1R0R) + Filter));
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables L3 and L4 filtering process.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None.
+ */
+void HAL_ETHEx_EnableL3L4Filtering(ETH_HandleTypeDef *heth)
+{
+ /* Enable L3/L4 filter */
+ SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE);
+}
+
+/**
+ * @brief Disables L3 and L4 filtering process.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None.
+ */
+void HAL_ETHEx_DisableL3L4Filtering(ETH_HandleTypeDef *heth)
+{
+ /* Disable L3/L4 filter */
+ CLEAR_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE);
+}
+
+/**
+ * @brief Get the VLAN Configuration for Receive Packets.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pVlanConfig: pointer to a ETH_RxVLANConfigTypeDef structure
+ * that will contain the VLAN filter configuration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETHEx_GetRxVLANConfig(ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig)
+{
+ if(pVlanConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ pVlanConfig->InnerVLANTagInStatus = ((READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_EIVLRXS) >> 31) == 0U) ? DISABLE : ENABLE;
+ pVlanConfig->StripInnerVLANTag = READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_EIVLS);
+ pVlanConfig->InnerVLANTag = ((READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_ERIVLT) >> 27) == 0U) ? DISABLE : ENABLE;
+ pVlanConfig->DoubleVLANProcessing = ((READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_EDVLP) >> 26) == 0U) ? DISABLE : ENABLE;
+ pVlanConfig->VLANTagHashTableMatch = ((READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_VTHM) >> 25) == 0U) ? DISABLE : ENABLE;
+ pVlanConfig->VLANTagInStatus = ((READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_EVLRXS) >> 24) == 0U) ? DISABLE : ENABLE;
+ pVlanConfig->StripVLANTag = READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_EVLS);
+ pVlanConfig->VLANTypeCheck = READ_BIT(heth->Instance->MACVTR, (ETH_MACVTR_DOVLTC | ETH_MACVTR_ERSVLM | ETH_MACVTR_ESVL));
+ pVlanConfig->VLANTagInverceMatch = ((READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_VTIM) >> 17) == 0U) ? DISABLE : ENABLE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the VLAN Configuration for Receive Packets.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param pVlanConfig: pointer to a ETH_RxVLANConfigTypeDef structure
+ * that contains VLAN filter configuration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ETHEx_SetRxVLANConfig(ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig)
+{
+ if(pVlanConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Write config to MACVTR */
+ MODIFY_REG(heth->Instance->MACVTR, ETH_MACRXVLAN_MASK, (((uint32_t)pVlanConfig->InnerVLANTagInStatus << 31) |
+ pVlanConfig->StripInnerVLANTag |
+ ((uint32_t)pVlanConfig->InnerVLANTag << 27) |
+ ((uint32_t)pVlanConfig->DoubleVLANProcessing << 26) |
+ ((uint32_t)pVlanConfig->VLANTagHashTableMatch << 25) |
+ ((uint32_t)pVlanConfig->VLANTagInStatus << 24) |
+ pVlanConfig->StripVLANTag |
+ pVlanConfig->VLANTypeCheck |
+ ((uint32_t)pVlanConfig->VLANTagInverceMatch << 17)));
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the VLAN Hash Table
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param VLANHashTable: VLAN hash table 16 bit value
+ * @retval None
+ */
+void HAL_ETHEx_SetVLANHashTable(ETH_HandleTypeDef *heth, uint32_t VLANHashTable)
+{
+ MODIFY_REG(heth->Instance->MACVHTR, ETH_MACVHTR_VLHT, VLANHashTable);
+}
+
+/**
+ * @brief Get the VLAN Configuration for Transmit Packets.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param VLANTag: Selects the vlan tag, this parameter must be one of the following
+ * ETH_OUTER_TX_VLANTAG
+ * ETH_INNER_TX_VLANTAG
+ * @param pVlanConfig: pointer to a ETH_TxVLANConfigTypeDef structure
+ * that will contain the Tx VLAN filter configuration.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_ETHEx_GetTxVLANConfig(ETH_HandleTypeDef *heth, uint32_t VLANTag ,ETH_TxVLANConfigTypeDef *pVlanConfig)
+{
+ if (pVlanConfig == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(VLANTag == ETH_INNER_TX_VLANTAG)
+ {
+ pVlanConfig->SourceTxDesc = ((READ_BIT(heth->Instance->MACIVIR, ETH_MACVIR_VLTI) >> 20) == 0U) ? DISABLE : ENABLE;
+ pVlanConfig->SVLANType = ((READ_BIT(heth->Instance->MACIVIR, ETH_MACVIR_CSVL) >> 19) == 0U) ? DISABLE : ENABLE;
+ pVlanConfig->VLANTagControl = READ_BIT(heth->Instance->MACIVIR, (ETH_MACVIR_VLP | ETH_MACVIR_VLC));
+ }
+ else
+ {
+ pVlanConfig->SourceTxDesc = ((READ_BIT(heth->Instance->MACVIR, ETH_MACVIR_VLTI) >> 20) == 0U) ? DISABLE : ENABLE;
+ pVlanConfig->SVLANType = ((READ_BIT(heth->Instance->MACVIR, ETH_MACVIR_CSVL) >> 19) == 0U) ? DISABLE : ENABLE;
+ pVlanConfig->VLANTagControl = READ_BIT(heth->Instance->MACVIR, (ETH_MACVIR_VLP | ETH_MACVIR_VLC));
+ }
+
+ return HAL_OK;;
+}
+
+/**
+ * @brief Set the VLAN Configuration for Transmit Packets.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param VLANTag: Selects the vlan tag, this parameter must be one of the following
+ * ETH_OUTER_TX_VLANTAG
+ * ETH_INNER_TX_VLANTAG
+ * @param pVlanConfig: pointer to a ETH_TxVLANConfigTypeDef structure
+ * that contains Tx VLAN filter configuration.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_ETHEx_SetTxVLANConfig(ETH_HandleTypeDef *heth, uint32_t VLANTag ,ETH_TxVLANConfigTypeDef *pVlanConfig)
+{
+ if(VLANTag == ETH_INNER_TX_VLANTAG)
+ {
+ MODIFY_REG(heth->Instance->MACIVIR, ETH_MACTXVLAN_MASK, (((uint32_t)pVlanConfig->SourceTxDesc << 20) |
+ ((uint32_t)pVlanConfig->SVLANType << 19) |
+ pVlanConfig->VLANTagControl));
+ /* Enable Double VLAN processing */
+ SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_EDVLP);
+ }
+ else
+ {
+ MODIFY_REG(heth->Instance->MACVIR, ETH_MACTXVLAN_MASK, (((uint32_t)pVlanConfig->SourceTxDesc << 20) |
+ ((uint32_t)pVlanConfig->SVLANType << 19) |
+ pVlanConfig->VLANTagControl));
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the VLAN Tag Identifier for Transmit Packets.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param VLANTag: Selects the vlan tag, this parameter must be one of the following
+ * ETH_OUTER_TX_VLANTAG
+ * ETH_INNER_TX_VLANTAG
+ * @param VLANIdentifier: VLAN Identifier 16 bit value
+ * @retval None
+ */
+void HAL_ETHEx_SetTxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t VLANTag ,uint32_t VLANIdentifier)
+{
+ if(VLANTag == ETH_INNER_TX_VLANTAG)
+ {
+ MODIFY_REG(heth->Instance->MACIVIR, ETH_MACVIR_VLT, VLANIdentifier);
+ }
+ else
+ {
+ MODIFY_REG(heth->Instance->MACVIR, ETH_MACVIR_VLT, VLANIdentifier);
+ }
+}
+
+/**
+ * @brief Enables the VLAN Tag Filtering process.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None.
+ */
+void HAL_ETHEx_EnableVLANProcessing(ETH_HandleTypeDef *heth)
+{
+ /* Enable VLAN processing */
+ SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_VTFE);
+}
+
+/**
+ * @brief Disables the VLAN Tag Filtering process.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None.
+ */
+void HAL_ETHEx_DisableVLANProcessing(ETH_HandleTypeDef *heth)
+{
+ /* Disable VLAN processing */
+ CLEAR_BIT(heth->Instance->MACPFR, ETH_MACPFR_VTFE);
+}
+
+/**
+ * @brief Enters the Low Power Idle (LPI) mode
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @param TxAutomate: Enable/Disbale automate enter/exit LPI mode.
+ * @param TxClockStop: Enable/Disbale Tx clock stop in LPI mode.
+ * @retval None
+ */
+void HAL_ETHEx_EnterLPIMode(ETH_HandleTypeDef *heth, FunctionalState TxAutomate, FunctionalState TxClockStop)
+{
+ /* Enable LPI Interrupts */
+ __HAL_ETH_MAC_ENABLE_IT(heth, ETH_MACIER_LPIIE);
+
+ /* Write to LPI Control register: Enter low power mode */
+ MODIFY_REG(heth->Instance->MACLCSR, (ETH_MACLCSR_LPIEN | ETH_MACLCSR_LPITXA | ETH_MACLCSR_LPITCSE), (((uint32_t)TxAutomate << 19) |
+ ((uint32_t)TxClockStop << 21) |
+ ETH_MACLCSR_LPIEN));
+}
+
+/**
+ * @brief Exits the Low Power Idle (LPI) mode.
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval None
+ */
+void HAL_ETHEx_ExitLPIMode(ETH_HandleTypeDef *heth)
+{
+ /* Clear the LPI Config and exit low power mode */
+ CLEAR_BIT(heth->Instance->MACLCSR, (ETH_MACLCSR_LPIEN | ETH_MACLCSR_LPITXA | ETH_MACLCSR_LPITCSE));
+
+ /* Enable LPI Interrupts */
+ __HAL_ETH_MAC_DISABLE_IT(heth, ETH_MACIER_LPIIE);
+}
+
+
+/**
+ * @brief Returns the ETH MAC LPI event
+ * @param heth: pointer to a ETH_HandleTypeDef structure that contains
+ * the configuration information for ETHERNET module
+ * @retval ETH MAC WakeUp event
+ */
+uint32_t HAL_ETHEx_GetMACLPIEvent(ETH_HandleTypeDef *heth)
+{
+ return heth->MACLPIEvent;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* ETH */
+
+#endif /* HAL_ETH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_exti.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_exti.c
new file mode 100644
index 0000000000..ffb5deeffb
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_exti.c
@@ -0,0 +1,877 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ @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 throught multiplexer.
+
+ (+) PendClearSource used to set the D3 Smart Run Domain autoamtic pend clear soure.
+ 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 selcted :
+ 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 selcted :
+ 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 selcted :
+ 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 selcted :
+ 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 selcted :
+ 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 exiting handle as parameter.
+ (++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
+
+ (#) Clear Exti configuration of a dedicated line using HAL_EXTI_GetConfigLine().
+ (++) Provide exiting handle as parameter.
+
+ (#) Register callback to treat Exti interrupts using HAL_EXTI_RegisterCallback().
+ (++) Provide exiting handle as first parameter.
+ (++) Provide which callback will be registered using one value from
+ EXTI_CallbackIDTypeDef.
+ (++) Provide callback function pointer.
+
+ (#) Get interrupt pending bit using HAL_EXTI_GetPending().
+
+ (#) Clear interrupt pending bit using HAL_EXTI_GetPending().
+
+ (#) Generate software interrupt using HAL_EXTI_GenerateSWI().
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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*/
+
+ /* 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;
+ }
+ else
+ {
+ pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
+ }
+
+ /* 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 * (3UL - (linepos & 0x03UL)))) >> 24U);
+ }
+ else
+ {
+ pExtiConfig->GPIOSel = 0x00U;
+ }
+ }
+ else
+ {
+ pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
+ pExtiConfig->GPIOSel = 0x00U;
+ }
+
+ /* 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 PMR unset, then no pend clear source is used */
+ pExtiConfig->PendClearSource = EXTI_D3_PENDCLR_SRC_NONE;
+ }
+ else
+ {
+ /* 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));
+ }
+ }
+ else
+ {
+ /* if line wakeup target is not any, then no pend clear source is used */
+ pExtiConfig->PendClearSource = EXTI_D3_PENDCLR_SRC_NONE;
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Clear whole configuration of a dedicated Exti line.
+ * @param hexti Exti handle.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+ 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(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(EXTI_HandleTypeDef *hexti, uint32_t Edge)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Check parameters */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+ assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
+ 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(EXTI_HandleTypeDef *hexti, uint32_t Edge)
+{
+ __IO uint32_t *regaddr;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Check parameters */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+ assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
+ 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(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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_fdcan.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_fdcan.c
new file mode 100644
index 0000000000..7505fd5a16
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_fdcan.c
@@ -0,0 +1,6169 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_fdcan.c
+ * @author MCD Application Team
+ * @brief FDCAN HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Flexible DataRate Controller Area Network
+ * (FDCAN) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Configuration and Control functions
+ * + Peripheral State and Error functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Initialize the FDCAN peripheral using HAL_FDCAN_Init function.
+
+ (#) If needed , configure the reception filters and optional features using
+ the following configuration functions:
+ (++) HAL_FDCAN_ConfigClockCalibration
+ (++) HAL_FDCAN_ConfigFilter
+ (++) HAL_FDCAN_ConfigGlobalFilter
+ (++) HAL_FDCAN_ConfigExtendedIdMask
+ (++) HAL_FDCAN_ConfigRxFifoOverwrite
+ (++) HAL_FDCAN_ConfigFifoWatermark
+ (++) HAL_FDCAN_ConfigRamWatchdog
+ (++) HAL_FDCAN_ConfigTimestampCounter
+ (++) HAL_FDCAN_EnableTimestampCounter
+ (++) HAL_FDCAN_DisableTimestampCounter
+ (++) HAL_FDCAN_ConfigTimeoutCounter
+ (++) HAL_FDCAN_EnableTimeoutCounter
+ (++) HAL_FDCAN_DisableTimeoutCounter
+ (++) HAL_FDCAN_ConfigTxDelayCompensation
+ (++) HAL_FDCAN_EnableTxDelayCompensation
+ (++) HAL_FDCAN_DisableTxDelayCompensation
+ (++) HAL_FDCAN_EnableISOMode
+ (++) HAL_FDCAN_DisableISOMode
+ (++) HAL_FDCAN_EnableEdgeFiltering
+ (++) HAL_FDCAN_DisableEdgeFiltering
+ (++) HAL_FDCAN_TT_ConfigOperation
+ (++) HAL_FDCAN_TT_ConfigReferenceMessage
+ (++) HAL_FDCAN_TT_ConfigTrigger
+
+ (#) Start the FDCAN module using HAL_FDCAN_Start function. At this level
+ the node is active on the bus: it can send and receive messages.
+
+ (#) The following Tx control functions can only be called when the FDCAN
+ module is started:
+ (++) HAL_FDCAN_AddMessageToTxFifoQ
+ (++) HAL_FDCAN_EnableTxBufferRequest
+ (++) HAL_FDCAN_AbortTxRequest
+
+ (#) After having submitted a Tx request in Tx Fifo or Queue, it is possible to
+ get Tx buffer location used to place the Tx request thanks to
+ HAL_FDCAN_GetLatestTxFifoQRequestBuffer API.
+ It is then possible to abort later on the corresponding Tx Request using
+ HAL_FDCAN_AbortTxRequest API.
+
+ (#) When a message is received into the FDCAN message RAM, it can be
+ retrieved using the HAL_FDCAN_GetRxMessage function.
+
+ (#) Calling the HAL_FDCAN_Stop function stops the FDCAN module by entering
+ it to initialization mode and re-enabling access to configuration
+ registers through the configuration functions listed here above.
+
+ (#) All other control functions can be called any time after initialization
+ phase, no matter if the FDCAN module is started or stoped.
+
+ *** Polling mode operation ***
+ ==============================
+
+ [..]
+ (#) Reception and transmission states can be monitored via the following
+ functions:
+ (++) HAL_FDCAN_IsRxBufferMessageAvailable
+ (++) HAL_FDCAN_IsTxBufferMessagePending
+ (++) HAL_FDCAN_GetRxFifoFillLevel
+ (++) HAL_FDCAN_GetTxFifoFreeLevel
+
+ *** Interrupt mode operation ***
+ ================================
+ [..]
+ (#) There are two interrupt lines: line 0 and 1.
+ By default, all interrupts are assigned to line 0. Interrupt lines
+ can be configured using HAL_FDCAN_ConfigInterruptLines function.
+
+ (#) Notifications are activated using HAL_FDCAN_ActivateNotification
+ function. Then, the process can be controlled through one of the
+ available user callbacks: HAL_FDCAN_xxxCallback.
+
+ *** Callback registration ***
+ =============================================
+
+ The compilation define USE_HAL_FDCAN_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Function @ref HAL_FDCAN_RegisterCallback() or HAL_FDCAN_RegisterXXXCallback()
+ to register an interrupt callback.
+
+ Function @ref HAL_FDCAN_RegisterCallback() allows to register following callbacks:
+ (+) TxFifoEmptyCallback : Tx Fifo Empty Callback.
+ (+) RxBufferNewMessageCallback : Rx Buffer New Message Callback.
+ (+) HighPriorityMessageCallback : High Priority Message Callback.
+ (+) TimestampWraparoundCallback : Timestamp Wraparound Callback.
+ (+) TimeoutOccurredCallback : Timeout Occurred Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) MspInitCallback : FDCAN MspInit.
+ (+) MspDeInitCallback : FDCAN MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ For specific callbacks ClockCalibrationCallback, TxEventFifoCallback, RxFifo0Callback, RxFifo1Callback,
+ TxBufferCompleteCallback, TxBufferAbortCallback, ErrorStatusCallback, TT_ScheduleSyncCallback, TT_TimeMarkCallback,
+ TT_StopWatchCallback and TT_GlobalTimeCallback, use dedicated register callbacks :
+ respectively @ref HAL_FDCAN_RegisterClockCalibrationCallback(), @ref HAL_FDCAN_RegisterTxEventFifoCallback(),
+ @ref HAL_FDCAN_RegisterRxFifo0Callback(), @ref HAL_FDCAN_RegisterRxFifo1Callback(),
+ @ref HAL_FDCAN_RegisterTxBufferCompleCallback(), @ref HAL_FDCAN_RegisterTxBufferAbortCallback(),
+ @ref HAL_FDCAN_RegisterErrorStatusCallback(), @ref HAL_FDCAN_TT_RegisterScheduleSyncCallback(),
+ @ref HAL_FDCAN_TT_RegisterTimeMarkCallback(), @ref HAL_FDCAN_TT_RegisterStopWatchCallback() and
+ @ref HAL_FDCAN_TT_RegisterGlobalTimeCallback().
+
+ Use function @ref HAL_FDCAN_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ @ref HAL_FDCAN_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxFifoEmptyCallback : Tx Fifo Empty Callback.
+ (+) RxBufferNewMessageCallback : Rx Buffer New Message Callback.
+ (+) HighPriorityMessageCallback : High Priority Message Callback.
+ (+) TimestampWraparoundCallback : Timestamp Wraparound Callback.
+ (+) TimeoutOccurredCallback : Timeout Occurred Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) MspInitCallback : FDCAN MspInit.
+ (+) MspDeInitCallback : FDCAN MspDeInit.
+
+ For specific callbacks ClockCalibrationCallback, TxEventFifoCallback, RxFifo0Callback,
+ RxFifo1Callback, TxBufferCompleteCallback, TxBufferAbortCallback, TT_ScheduleSyncCallback,
+ TT_TimeMarkCallback, TT_StopWatchCallback and TT_GlobalTimeCallback, use dedicated
+ register callbacks : respectively @ref HAL_FDCAN_UnRegisterClockCalibrationCallback(),
+ @ref HAL_FDCAN_UnRegisterTxEventFifoCallback(), @ref HAL_FDCAN_UnRegisterRxFifo0Callback(),
+ @ref HAL_FDCAN_UnRegisterRxFifo1Callback(), @ref HAL_FDCAN_UnRegisterTxBufferCompleCallback(),
+ @ref HAL_FDCAN_UnRegisterTxBufferAbortCallback(), @ref HAL_FDCAN_UnRegisterErrorStatusCallback(),
+ @ref HAL_FDCAN_TT_UnRegisterScheduleSyncCallback(), @ref HAL_FDCAN_TT_UnRegisterTimeMarkCallback(),
+ @ref HAL_FDCAN_TT_UnRegisterStopWatchCallback() and @ref HAL_FDCAN_TT_UnRegisterGlobalTimeCallback().
+
+ By default, after the @ref HAL_FDCAN_Init() and when the state is HAL_FDCAN_STATE_RESET,
+ all callbacks are set to the corresponding weak functions:
+ examples @ref HAL_FDCAN_ErrorCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak function in the @ref HAL_FDCAN_Init()/ @ref HAL_FDCAN_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ if not, MspInit or MspDeInit are not null, the @ref HAL_FDCAN_Init()/ @ref HAL_FDCAN_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in HAL_FDCAN_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_FDCAN_STATE_READY or HAL_FDCAN_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 @ref HAL_FDCAN_RegisterCallback() before calling @ref HAL_FDCAN_DeInit()
+ or @ref HAL_FDCAN_Init() function.
+
+ When The compilation define USE_HAL_FDCAN_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
+
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup FDCAN FDCAN
+ * @brief FDCAN HAL module driver
+ * @{
+ */
+
+#ifdef HAL_FDCAN_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup FDCAN_Private_Constants
+ * @{
+ */
+#define FDCAN_TIMEOUT_VALUE 10U
+
+#define FDCAN_TX_EVENT_FIFO_MASK (FDCAN_IR_TEFL | FDCAN_IR_TEFF | FDCAN_IR_TEFW | FDCAN_IR_TEFN)
+#define FDCAN_RX_FIFO0_MASK (FDCAN_IR_RF0L | FDCAN_IR_RF0F | FDCAN_IR_RF0W | FDCAN_IR_RF0N)
+#define FDCAN_RX_FIFO1_MASK (FDCAN_IR_RF1L | FDCAN_IR_RF1F | FDCAN_IR_RF1W | FDCAN_IR_RF1N)
+#define FDCAN_ERROR_MASK (FDCAN_IR_ELO | FDCAN_IR_WDI | FDCAN_IR_PEA | FDCAN_IR_PED | FDCAN_IR_ARA)
+#define FDCAN_ERROR_STATUS_MASK (FDCAN_IR_EP | FDCAN_IR_EW | FDCAN_IR_BO)
+#define FDCAN_TT_SCHEDULE_SYNC_MASK (FDCAN_TTIR_SBC | FDCAN_TTIR_SMC | FDCAN_TTIR_CSM | FDCAN_TTIR_SOG)
+#define FDCAN_TT_TIME_MARK_MASK (FDCAN_TTIR_RTMI | FDCAN_TTIR_TTMI)
+#define FDCAN_TT_GLOBAL_TIME_MASK (FDCAN_TTIR_GTW | FDCAN_TTIR_GTD)
+#define FDCAN_TT_DISTURBING_ERROR_MASK (FDCAN_TTIR_GTE | FDCAN_TTIR_TXU | FDCAN_TTIR_TXO | \
+ FDCAN_TTIR_SE1 | FDCAN_TTIR_SE2 | FDCAN_TTIR_ELC)
+#define FDCAN_TT_FATAL_ERROR_MASK (FDCAN_TTIR_IWT | FDCAN_TTIR_WT | FDCAN_TTIR_AW | FDCAN_TTIR_CER)
+
+#define FDCAN_ELEMENT_MASK_STDID ((uint32_t)0x1FFC0000U) /* Standard Identifier */
+#define FDCAN_ELEMENT_MASK_EXTID ((uint32_t)0x1FFFFFFFU) /* Extended Identifier */
+#define FDCAN_ELEMENT_MASK_RTR ((uint32_t)0x20000000U) /* Remote Transmission Request */
+#define FDCAN_ELEMENT_MASK_XTD ((uint32_t)0x40000000U) /* Extended Identifier */
+#define FDCAN_ELEMENT_MASK_ESI ((uint32_t)0x80000000U) /* Error State Indicator */
+#define FDCAN_ELEMENT_MASK_TS ((uint32_t)0x0000FFFFU) /* Timestamp */
+#define FDCAN_ELEMENT_MASK_DLC ((uint32_t)0x000F0000U) /* Data Length Code */
+#define FDCAN_ELEMENT_MASK_BRS ((uint32_t)0x00100000U) /* Bit Rate Switch */
+#define FDCAN_ELEMENT_MASK_FDF ((uint32_t)0x00200000U) /* FD Format */
+#define FDCAN_ELEMENT_MASK_EFC ((uint32_t)0x00800000U) /* Event FIFO Control */
+#define FDCAN_ELEMENT_MASK_MM ((uint32_t)0xFF000000U) /* Message Marker */
+#define FDCAN_ELEMENT_MASK_FIDX ((uint32_t)0x7F000000U) /* Filter Index */
+#define FDCAN_ELEMENT_MASK_ANMF ((uint32_t)0x80000000U) /* Accepted Non-matching Frame */
+#define FDCAN_ELEMENT_MASK_ET ((uint32_t)0x00C00000U) /* Event type */
+
+#define FDCAN_MESSAGE_RAM_SIZE 0x2800U
+#define FDCAN_MESSAGE_RAM_END_ADDRESS (SRAMCAN_BASE + FDCAN_MESSAGE_RAM_SIZE - 0x4U) /* The Message RAM has a width of 4 Bytes */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+static const uint8_t DLCtoBytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};
+
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup FDCAN_Private_Functions_Prototypes
+ * @{
+ */
+static HAL_StatusTypeDef FDCAN_CalcultateRamBlockAddresses(FDCAN_HandleTypeDef *hfdcan);
+static void FDCAN_CopyMessageToRAM(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData, uint32_t BufferIndex);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup FDCAN_Exported_Functions FDCAN Exported Functions
+ * @{
+ */
+
+/** @defgroup FDCAN_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 FDCAN.
+ (+) De-initialize the FDCAN.
+ (+) Enter FDCAN peripheral in power down mode.
+ (+) Exit power down mode.
+ (+) Register callbacks.
+ (+) Unregister callbacks.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the FDCAN peripheral according to the specified
+ * parameters in the FDCAN_InitTypeDef structure.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef status;
+ const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};
+
+ /* Check FDCAN handle */
+ if (hfdcan == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check FDCAN instance */
+ if (hfdcan->Instance == FDCAN1)
+ {
+ hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);
+ }
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
+ assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));
+ assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));
+ assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
+ assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
+ assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));
+ assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));
+ assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));
+ assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));
+ if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
+ {
+ assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));
+ assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));
+ assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));
+ assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));
+ }
+ assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));
+ assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));
+ assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
+ if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
+ {
+ assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));
+ }
+ assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));
+ if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
+ {
+ assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));
+ }
+ assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));
+ if (hfdcan->Init.RxBuffersNbr > 0U)
+ {
+ assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));
+ }
+ assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));
+ assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));
+ if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
+ {
+ assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
+ }
+ if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
+ {
+ assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));
+ }
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ if (hfdcan->State == HAL_FDCAN_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hfdcan->Lock = HAL_UNLOCKED;
+
+ /* Reset callbacks to legacy functions */
+ hfdcan->ClockCalibrationCallback = HAL_FDCAN_ClockCalibrationCallback; /* Legacy weak ClockCalibrationCallback */
+ hfdcan->TxEventFifoCallback = HAL_FDCAN_TxEventFifoCallback; /* Legacy weak TxEventFifoCallback */
+ hfdcan->RxFifo0Callback = HAL_FDCAN_RxFifo0Callback; /* Legacy weak RxFifo0Callback */
+ hfdcan->RxFifo1Callback = HAL_FDCAN_RxFifo1Callback; /* Legacy weak RxFifo1Callback */
+ hfdcan->TxFifoEmptyCallback = HAL_FDCAN_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */
+ hfdcan->TxBufferCompleteCallback = HAL_FDCAN_TxBufferCompleteCallback; /* Legacy weak TxBufferCompleteCallback */
+ hfdcan->TxBufferAbortCallback = HAL_FDCAN_TxBufferAbortCallback; /* Legacy weak TxBufferAbortCallback */
+ hfdcan->RxBufferNewMessageCallback = HAL_FDCAN_RxBufferNewMessageCallback; /* Legacy weak RxBufferNewMessageCallback */
+ hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */
+ hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */
+ hfdcan->TimeoutOccurredCallback = HAL_FDCAN_TimeoutOccurredCallback; /* Legacy weak TimeoutOccurredCallback */
+ hfdcan->ErrorCallback = HAL_FDCAN_ErrorCallback; /* Legacy weak ErrorCallback */
+ hfdcan->ErrorStatusCallback = HAL_FDCAN_ErrorStatusCallback; /* Legacy weak ErrorStatusCallback */
+ hfdcan->TT_ScheduleSyncCallback = HAL_FDCAN_TT_ScheduleSyncCallback; /* Legacy weak TT_ScheduleSyncCallback */
+ hfdcan->TT_TimeMarkCallback = HAL_FDCAN_TT_TimeMarkCallback; /* Legacy weak TT_TimeMarkCallback */
+ hfdcan->TT_StopWatchCallback = HAL_FDCAN_TT_StopWatchCallback; /* Legacy weak TT_StopWatchCallback */
+ hfdcan->TT_GlobalTimeCallback = HAL_FDCAN_TT_GlobalTimeCallback; /* Legacy weak TT_GlobalTimeCallback */
+
+ if (hfdcan->MspInitCallback == NULL)
+ {
+ hfdcan->MspInitCallback = HAL_FDCAN_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware: CLOCK, NVIC */
+ hfdcan->MspInitCallback(hfdcan);
+ }
+#else
+ if (hfdcan->State == HAL_FDCAN_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hfdcan->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware: CLOCK, NVIC */
+ HAL_FDCAN_MspInit(hfdcan);
+ }
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+
+ /* Exit from Sleep mode */
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check Sleep mode acknowledge */
+ while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)
+ {
+ if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Request initialisation */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until the INIT bit into CCCR register is set */
+ while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Enable configuration change */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);
+
+ /* Set the no automatic retransmission */
+ if (hfdcan->Init.AutoRetransmission == ENABLE)
+ {
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
+ }
+ else
+ {
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
+ }
+
+ /* Set the transmit pause feature */
+ if (hfdcan->Init.TransmitPause == ENABLE)
+ {
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
+ }
+ else
+ {
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
+ }
+
+ /* Set the Protocol Exception Handling */
+ if (hfdcan->Init.ProtocolException == ENABLE)
+ {
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
+ }
+ else
+ {
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
+ }
+
+ /* Set FDCAN Frame Format */
+ MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);
+
+ /* Reset FDCAN Operation Mode */
+ CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));
+ CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
+
+ /* Set FDCAN Operating Mode:
+ | Normal | Restricted | Bus | Internal | External
+ | | Operation | Monitoring | LoopBack | LoopBack
+ CCCR.TEST | 0 | 0 | 0 | 1 | 1
+ CCCR.MON | 0 | 0 | 1 | 1 | 0
+ TEST.LBCK | 0 | 0 | 0 | 1 | 1
+ CCCR.ASM | 0 | 1 | 0 | 0 | 0
+ */
+ if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)
+ {
+ /* Enable Restricted Operation mode */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
+ }
+ else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
+ {
+ if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)
+ {
+ /* Enable write access to TEST register */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);
+
+ /* Enable LoopBack mode */
+ SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
+
+ if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)
+ {
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
+ }
+ }
+ else
+ {
+ /* Enable bus monitoring mode */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
+ }
+ }
+ else
+ {
+ /* Nothing to do: normal mode */
+ }
+
+ /* Set the nominal bit timing register */
+ hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \
+ (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos) | \
+ (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos) | \
+ (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));
+
+ /* If FD operation with BRS is selected, set the data bit timing register */
+ if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
+ {
+ hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \
+ (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos) | \
+ (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos) | \
+ (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));
+ }
+
+ if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
+ {
+ /* Select between Tx FIFO and Tx Queue operation modes */
+ SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);
+ }
+
+ /* Configure Tx element size */
+ if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
+ {
+ MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);
+ }
+
+ /* Configure Rx FIFO 0 element size */
+ if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
+ {
+ MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));
+ }
+
+ /* Configure Rx FIFO 1 element size */
+ if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
+ {
+ MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));
+ }
+
+ /* Configure Rx buffer element size */
+ if (hfdcan->Init.RxBuffersNbr > 0U)
+ {
+ MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));
+ }
+
+ /* By default operation mode is set to Event-driven communication.
+ If Time-triggered communication is needed, user should call the
+ HAL_FDCAN_TT_ConfigOperation function just after the HAL_FDCAN_Init */
+ if (hfdcan->Instance == FDCAN1)
+ {
+ CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);
+ }
+
+ /* Initialize the Latest Tx FIFO/Queue request buffer index */
+ hfdcan->LatestTxFifoQRequest = 0U;
+
+ /* Initialize the error code */
+ hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
+
+ /* Initialize the FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_READY;
+
+ /* Calculate each RAM block address */
+ status = FDCAN_CalcultateRamBlockAddresses(hfdcan);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Deinitializes the FDCAN peripheral registers to their default reset values.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Check FDCAN handle */
+ if (hfdcan == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
+
+ /* Stop the FDCAN module: return value is voluntary ignored */
+ (void)HAL_FDCAN_Stop(hfdcan);
+
+ /* Disable Interrupt lines */
+ CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ if (hfdcan->MspDeInitCallback == NULL)
+ {
+ hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: CLOCK, NVIC */
+ hfdcan->MspDeInitCallback(hfdcan);
+#else
+ /* DeInit the low level hardware: CLOCK, NVIC */
+ HAL_FDCAN_MspDeInit(hfdcan);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+
+ /* Reset the FDCAN ErrorCode */
+ hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_RESET;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the FDCAN MSP.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval None
+ */
+__weak void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes the FDCAN MSP.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval None
+ */
+__weak void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Enter FDCAN peripheral in sleep mode.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_EnterPowerDownMode(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t tickstart;
+
+ /* Request clock stop */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until FDCAN is ready for power down */
+ while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Exit power down mode.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ExitPowerDownMode(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t tickstart;
+
+ /* Reset clock stop request */
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until FDCAN exits sleep mode */
+ while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)
+ {
+ if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Enter normal operation */
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+/**
+ * @brief Register a FDCAN CallBack.
+ * To be used instead of the weak predefined callback
+ * @param hfdcan pointer to a FDCAN_HandleTypeDef structure that contains
+ * the configuration information for FDCAN module
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_FDCAN_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty callback ID
+ * @arg @ref HAL_FDCAN_RX_BUFFER_NEW_MSG_CB_ID Rx buffer new message callback ID
+ * @arg @ref HAL_FDCAN_HIGH_PRIO_MESSAGE_CB_ID High priority message callback ID
+ * @arg @ref HAL_FDCAN_TIMESTAMP_WRAPAROUND_CB_ID Timestamp wraparound callback ID
+ * @arg @ref HAL_FDCAN_TIMEOUT_OCCURRED_CB_ID Timeout occurred callback ID
+ * @arg @ref HAL_FDCAN_ERROR_CALLBACK_CB_ID Error callback ID
+ * @arg @ref HAL_FDCAN_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_FDCAN_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterCallback(FDCAN_HandleTypeDef *hfdcan, HAL_FDCAN_CallbackIDTypeDef CallbackID, void (* pCallback)(FDCAN_HandleTypeDef *_hFDCAN))
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_FDCAN_TX_FIFO_EMPTY_CB_ID :
+ hfdcan->TxFifoEmptyCallback = pCallback;
+ break;
+
+ case HAL_FDCAN_RX_BUFFER_NEW_MSG_CB_ID :
+ hfdcan->RxBufferNewMessageCallback = pCallback;
+ break;
+
+ case HAL_FDCAN_HIGH_PRIO_MESSAGE_CB_ID :
+ hfdcan->HighPriorityMessageCallback = pCallback;
+ break;
+
+ case HAL_FDCAN_TIMESTAMP_WRAPAROUND_CB_ID :
+ hfdcan->TimestampWraparoundCallback = pCallback;
+ break;
+
+ case HAL_FDCAN_TIMEOUT_OCCURRED_CB_ID :
+ hfdcan->TimeoutOccurredCallback = pCallback;
+ break;
+
+ case HAL_FDCAN_ERROR_CALLBACK_CB_ID :
+ hfdcan->ErrorCallback = pCallback;
+ break;
+
+ case HAL_FDCAN_MSPINIT_CB_ID :
+ hfdcan->MspInitCallback = pCallback;
+ break;
+
+ case HAL_FDCAN_MSPDEINIT_CB_ID :
+ hfdcan->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hfdcan->State == HAL_FDCAN_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_FDCAN_MSPINIT_CB_ID :
+ hfdcan->MspInitCallback = pCallback;
+ break;
+
+ case HAL_FDCAN_MSPDEINIT_CB_ID :
+ hfdcan->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a FDCAN CallBack.
+ * FDCAN callback is redirected to the weak predefined callback
+ * @param hfdcan pointer to a FDCAN_HandleTypeDef structure that contains
+ * the configuration information for FDCAN module
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_FDCAN_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty callback ID
+ * @arg @ref HAL_FDCAN_RX_BUFFER_NEW_MSG_CB_ID Rx buffer new message callback ID
+ * @arg @ref HAL_FDCAN_HIGH_PRIO_MESSAGE_CB_ID High priority message callback ID
+ * @arg @ref HAL_FDCAN_TIMESTAMP_WRAPAROUND_CB_ID Timestamp wraparound callback ID
+ * @arg @ref HAL_FDCAN_TIMEOUT_OCCURRED_CB_ID Timeout occurred callback ID
+ * @arg @ref HAL_FDCAN_ERROR_CALLBACK_CB_ID Error callback ID
+ * @arg @ref HAL_FDCAN_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_FDCAN_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterCallback(FDCAN_HandleTypeDef *hfdcan, HAL_FDCAN_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_FDCAN_TX_FIFO_EMPTY_CB_ID :
+ hfdcan->TxFifoEmptyCallback = HAL_FDCAN_TxFifoEmptyCallback;
+ break;
+
+ case HAL_FDCAN_RX_BUFFER_NEW_MSG_CB_ID :
+ hfdcan->RxBufferNewMessageCallback = HAL_FDCAN_RxBufferNewMessageCallback;
+ break;
+
+ case HAL_FDCAN_HIGH_PRIO_MESSAGE_CB_ID :
+ hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback;
+ break;
+
+ case HAL_FDCAN_TIMESTAMP_WRAPAROUND_CB_ID :
+ hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback;
+ break;
+
+ case HAL_FDCAN_TIMEOUT_OCCURRED_CB_ID :
+ hfdcan->TimeoutOccurredCallback = HAL_FDCAN_TimeoutOccurredCallback;
+ break;
+
+ case HAL_FDCAN_ERROR_CALLBACK_CB_ID :
+ hfdcan->ErrorCallback = HAL_FDCAN_ErrorCallback;
+ break;
+
+ case HAL_FDCAN_MSPINIT_CB_ID :
+ hfdcan->MspInitCallback = HAL_FDCAN_MspInit;
+ break;
+
+ case HAL_FDCAN_MSPDEINIT_CB_ID :
+ hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hfdcan->State == HAL_FDCAN_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_FDCAN_MSPINIT_CB_ID :
+ hfdcan->MspInitCallback = HAL_FDCAN_MspInit;
+ break;
+
+ case HAL_FDCAN_MSPDEINIT_CB_ID :
+ hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register Clock Calibration FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_ClockCalibrationCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the Clock Calibration Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterClockCalibrationCallback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_ClockCalibrationCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->ClockCalibrationCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the Clock Calibration FDCAN Callback
+ * Clock Calibration FDCAN Callback is redirected to the weak HAL_FDCAN_ClockCalibrationCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterClockCalibrationCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->ClockCalibrationCallback = HAL_FDCAN_ClockCalibrationCallback; /* Legacy weak ClockCalibrationCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register Tx Event Fifo FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_TxEventFifoCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the Tx Event Fifo Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterTxEventFifoCallback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_TxEventFifoCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TxEventFifoCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the Tx Event Fifo FDCAN Callback
+ * Tx Event Fifo FDCAN Callback is redirected to the weak HAL_FDCAN_TxEventFifoCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterTxEventFifoCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TxEventFifoCallback = HAL_FDCAN_TxEventFifoCallback; /* Legacy weak TxEventFifoCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register Rx Fifo 0 FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_RxFifo0Callback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the Rx Fifo 0 Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterRxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_RxFifo0CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->RxFifo0Callback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the Rx Fifo 0 FDCAN Callback
+ * Rx Fifo 0 FDCAN Callback is redirected to the weak HAL_FDCAN_RxFifo0Callback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterRxFifo0Callback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->RxFifo0Callback = HAL_FDCAN_RxFifo0Callback; /* Legacy weak RxFifo0Callback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register Rx Fifo 1 FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_RxFifo1Callback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the Rx Fifo 1 Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterRxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_RxFifo1CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->RxFifo1Callback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the Rx Fifo 1 FDCAN Callback
+ * Rx Fifo 1 FDCAN Callback is redirected to the weak HAL_FDCAN_RxFifo1Callback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterRxFifo1Callback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->RxFifo1Callback = HAL_FDCAN_RxFifo1Callback; /* Legacy weak RxFifo1Callback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register Tx Buffer Complete FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_TxBufferCompleteCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the Tx Buffer Complete Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterTxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_TxBufferCompleteCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TxBufferCompleteCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the Tx Buffer Complete FDCAN Callback
+ * Tx Buffer Complete FDCAN Callback is redirected to the weak HAL_FDCAN_TxBufferCompleteCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterTxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TxBufferCompleteCallback = HAL_FDCAN_TxBufferCompleteCallback; /* Legacy weak TxBufferCompleteCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register Tx Buffer Abort FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_TxBufferAbortCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the Tx Buffer Abort Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterTxBufferAbortCallback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_TxBufferAbortCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TxBufferAbortCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the Tx Buffer Abort FDCAN Callback
+ * Tx Buffer Abort FDCAN Callback is redirected to the weak HAL_FDCAN_TxBufferAbortCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterTxBufferAbortCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TxBufferAbortCallback = HAL_FDCAN_TxBufferAbortCallback; /* Legacy weak TxBufferAbortCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register Error Status FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_ErrorStatusCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the Error Status Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_ErrorStatusCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->ErrorStatusCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the Error Status FDCAN Callback
+ * Error Status FDCAN Callback is redirected to the weak HAL_FDCAN_ErrorStatusCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->ErrorStatusCallback = HAL_FDCAN_ErrorStatusCallback; /* Legacy weak ErrorStatusCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register TT Schedule Synchronization FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_TT_ScheduleSyncCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the TT Schedule Synchronization Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterTTScheduleSyncCallback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_TT_ScheduleSyncCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TT_ScheduleSyncCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the TT Schedule Synchronization FDCAN Callback
+ * TT Schedule Synchronization Callback is redirected to the weak HAL_FDCAN_TT_ScheduleSyncCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterTTScheduleSyncCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TT_ScheduleSyncCallback = HAL_FDCAN_TT_ScheduleSyncCallback; /* Legacy weak TT_ScheduleSyncCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register TT Time Mark FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_TT_TimeMarkCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the TT Time Mark Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterTTTimeMarkCallback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_TT_TimeMarkCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TT_TimeMarkCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the TT Time Mark FDCAN Callback
+ * TT Time Mark Callback is redirected to the weak HAL_FDCAN_TT_TimeMarkCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterTTTimeMarkCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TT_TimeMarkCallback = HAL_FDCAN_TT_TimeMarkCallback; /* Legacy weak TT_TimeMarkCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register TT Stop Watch FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_TT_StopWatchCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the TT Stop Watch Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterTTStopWatchCallback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_TT_StopWatchCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TT_StopWatchCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the TT Stop Watch FDCAN Callback
+ * TT Stop Watch Callback is redirected to the weak HAL_FDCAN_TT_StopWatchCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterTTStopWatchCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TT_StopWatchCallback = HAL_FDCAN_TT_StopWatchCallback; /* Legacy weak TT_StopWatchCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register TT Global Time FDCAN Callback
+ * To be used instead of the weak HAL_FDCAN_TT_GlobalTimeCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @param pCallback pointer to the TT Global Time Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_RegisterTTGlobalTimeCallback(FDCAN_HandleTypeDef *hfdcan, pFDCAN_TT_GlobalTimeCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TT_GlobalTimeCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the TT Global Time FDCAN Callback
+ * TT Global Time Callback is redirected to the weak HAL_FDCAN_TT_GlobalTimeCallback() predefined callback
+ * @param hfdcan FDCAN handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_UnRegisterTTGlobalTimeCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ hfdcan->TT_GlobalTimeCallback = HAL_FDCAN_TT_GlobalTimeCallback; /* Legacy weak TT_GlobalTimeCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup FDCAN_Exported_Functions_Group2 Configuration functions
+ * @brief FDCAN Configuration functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Configuration functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) HAL_FDCAN_ConfigClockCalibration : Configure the FDCAN clock calibration unit
+ (+) HAL_FDCAN_GetClockCalibrationState : Get the clock calibration state
+ (+) HAL_FDCAN_ResetClockCalibrationState : Reset the clock calibration state
+ (+) HAL_FDCAN_GetClockCalibrationCounter : Get the clock calibration counters values
+ (+) HAL_FDCAN_ConfigFilter : Configure the FDCAN reception filters
+ (+) HAL_FDCAN_ConfigGlobalFilter : Configure the FDCAN global filter
+ (+) HAL_FDCAN_ConfigExtendedIdMask : Configure the extended ID mask
+ (+) HAL_FDCAN_ConfigRxFifoOverwrite : Configure the Rx FIFO operation mode
+ (+) HAL_FDCAN_ConfigFifoWatermark : Configure the FIFO watermark
+ (+) HAL_FDCAN_ConfigRamWatchdog : Configure the RAM watchdog
+ (+) HAL_FDCAN_ConfigTimestampCounter : Configure the timestamp counter
+ (+) HAL_FDCAN_EnableTimestampCounter : Enable the timestamp counter
+ (+) HAL_FDCAN_DisableTimestampCounter : Disable the timestamp counter
+ (+) HAL_FDCAN_GetTimestampCounter : Get the timestamp counter value
+ (+) HAL_FDCAN_ResetTimestampCounter : Reset the timestamp counter to zero
+ (+) HAL_FDCAN_ConfigTimeoutCounter : Configure the timeout counter
+ (+) HAL_FDCAN_EnableTimeoutCounter : Enable the timeout counter
+ (+) HAL_FDCAN_DisableTimeoutCounter : Disable the timeout counter
+ (+) HAL_FDCAN_GetTimeoutCounter : Get the timeout counter value
+ (+) HAL_FDCAN_ResetTimeoutCounter : Reset the timeout counter to its start value
+ (+) HAL_FDCAN_ConfigTxDelayCompensation : Configure the transmitter delay compensation
+ (+) HAL_FDCAN_EnableTxDelayCompensation : Enable the transmitter delay compensation
+ (+) HAL_FDCAN_DisableTxDelayCompensation : Disable the transmitter delay compensation
+ (+) HAL_FDCAN_EnableISOMode : Enable ISO 11898-1 protocol mode
+ (+) HAL_FDCAN_DisableISOMode : Disable ISO 11898-1 protocol mode
+ (+) HAL_FDCAN_EnableEdgeFiltering : Enable edge filtering during bus integration
+ (+) HAL_FDCAN_DisableEdgeFiltering : Disable edge filtering during bus integration
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the FDCAN clock calibration unit according to the specified
+ * parameters in the FDCAN_ClkCalUnitTypeDef structure.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param sCcuConfig pointer to an FDCAN_ClkCalUnitTypeDef structure that
+ * contains the clock calibration information
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigClockCalibration(FDCAN_HandleTypeDef *hfdcan, FDCAN_ClkCalUnitTypeDef *sCcuConfig)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_CLOCK_CALIBRATION(sCcuConfig->ClockCalibration));
+ if (sCcuConfig->ClockCalibration == FDCAN_CLOCK_CALIBRATION_DISABLE)
+ {
+ assert_param(IS_FDCAN_CKDIV(sCcuConfig->ClockDivider));
+ }
+ else
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(sCcuConfig->MinOscClkPeriods, 0xFFU));
+ assert_param(IS_FDCAN_CALIBRATION_FIELD_LENGTH(sCcuConfig->CalFieldLength));
+ assert_param(IS_FDCAN_MIN_VALUE(sCcuConfig->TimeQuantaPerBitTime, 4U));
+ assert_param(IS_FDCAN_MAX_VALUE(sCcuConfig->TimeQuantaPerBitTime, 0x25U));
+ assert_param(IS_FDCAN_MAX_VALUE(sCcuConfig->WatchdogStartValue, 0xFFFFU));
+ }
+
+ /* FDCAN1 should be initialized in order to use clock calibration */
+ if (hfdcan->Instance != FDCAN1)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ if (sCcuConfig->ClockCalibration == FDCAN_CLOCK_CALIBRATION_DISABLE)
+ {
+ /* Bypass clock calibration */
+ SET_BIT(FDCAN_CCU->CCFG, FDCANCCU_CCFG_BCC);
+
+ /* Configure clock divider */
+ MODIFY_REG(FDCAN_CCU->CCFG, FDCANCCU_CCFG_CDIV, sCcuConfig->ClockDivider);
+ }
+ else /* sCcuConfig->ClockCalibration == ENABLE */
+ {
+ /* Clock calibration unit generates time quanta clock */
+ CLEAR_BIT(FDCAN_CCU->CCFG, FDCANCCU_CCFG_BCC);
+
+ /* Configure clock calibration unit */
+ MODIFY_REG(FDCAN_CCU->CCFG,
+ (FDCANCCU_CCFG_TQBT | FDCANCCU_CCFG_CFL | FDCANCCU_CCFG_OCPM),
+ ((sCcuConfig->TimeQuantaPerBitTime << FDCANCCU_CCFG_TQBT_Pos) | sCcuConfig->CalFieldLength | (sCcuConfig->MinOscClkPeriods << FDCANCCU_CCFG_OCPM_Pos)));
+
+ /* Configure the start value of the calibration watchdog counter */
+ MODIFY_REG(FDCAN_CCU->CWD, FDCANCCU_CWD_WDC, sCcuConfig->WatchdogStartValue);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get the clock calibration state.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval State clock calibration state (can be a value of @arg FDCAN_calibration_state)
+ */
+uint32_t HAL_FDCAN_GetClockCalibrationState(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+
+ return (FDCAN_CCU->CSTAT & FDCANCCU_CSTAT_CALS);
+}
+
+/**
+ * @brief Reset the clock calibration state.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ResetClockCalibrationState(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* FDCAN1 should be initialized in order to use clock calibration */
+ if (hfdcan->Instance != FDCAN1)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ return HAL_ERROR;
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Calibration software reset */
+ SET_BIT(FDCAN_CCU->CCFG, FDCANCCU_CCFG_SWR);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get the clock calibration counter value.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param Counter clock calibration counter.
+ * This parameter can be a value of @arg FDCAN_calibration_counter.
+ * @retval Value clock calibration counter value
+ */
+uint32_t HAL_FDCAN_GetClockCalibrationCounter(FDCAN_HandleTypeDef *hfdcan, uint32_t Counter)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_CALIBRATION_COUNTER(Counter));
+
+ if (Counter == FDCAN_CALIB_TIME_QUANTA_COUNTER)
+ {
+ return ((FDCAN_CCU->CSTAT & FDCANCCU_CSTAT_TQC) >> FDCANCCU_CSTAT_TQC_Pos);
+ }
+ else if (Counter == FDCAN_CALIB_CLOCK_PERIOD_COUNTER)
+ {
+ return (FDCAN_CCU->CSTAT & FDCANCCU_CSTAT_OCPC);
+ }
+ else /* Counter == FDCAN_CALIB_WATCHDOG_COUNTER */
+ {
+ return ((FDCAN_CCU->CWD & FDCANCCU_CWD_WDV) >> FDCANCCU_CWD_WDV_Pos);
+ }
+}
+
+/**
+ * @brief Configure the FDCAN reception filter according to the specified
+ * parameters in the FDCAN_FilterTypeDef structure.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param sFilterConfig pointer to an FDCAN_FilterTypeDef structure that
+ * contains the filter configuration information
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)
+{
+ uint32_t FilterElementW1;
+ uint32_t FilterElementW2;
+ uint32_t *FilterAddress;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Check function parameters */
+ assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));
+ assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
+ if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));
+ assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));
+ }
+
+ if (sFilterConfig->IdType == FDCAN_STANDARD_ID)
+ {
+ /* Check function parameters */
+ assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));
+ assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));
+ if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));
+ assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));
+ }
+
+ /* Build filter element */
+ if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
+ {
+ FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U) |
+ (sFilterConfig->FilterID1 << 16U) |
+ (sFilterConfig->IsCalibrationMsg << 8U) |
+ sFilterConfig->RxBufferIndex);
+ }
+ else
+ {
+ FilterElementW1 = ((sFilterConfig->FilterType << 30U) |
+ (sFilterConfig->FilterConfig << 27U) |
+ (sFilterConfig->FilterID1 << 16U) |
+ sFilterConfig->FilterID2);
+ }
+
+ /* Calculate filter address */
+ FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));
+
+ /* Write filter element to the message RAM */
+ *FilterAddress = FilterElementW1;
+ }
+ else /* sFilterConfig->IdType == FDCAN_EXTENDED_ID */
+ {
+ /* Check function parameters */
+ assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));
+ assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));
+ if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));
+ assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));
+ }
+
+ /* Build first word of filter element */
+ FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);
+
+ /* Build second word of filter element */
+ if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
+ {
+ FilterElementW2 = sFilterConfig->RxBufferIndex;
+ }
+ else
+ {
+ FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);
+ }
+
+ /* Calculate filter address */
+ FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));
+
+ /* Write filter element to the message RAM */
+ *FilterAddress = FilterElementW1;
+ FilterAddress++;
+ *FilterAddress = FilterElementW2;
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the FDCAN global filter.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param NonMatchingStd Defines how received messages with 11-bit IDs that
+ * do not match any element of the filter list are treated.
+ * This parameter can be a value of @arg FDCAN_Non_Matching_Frames.
+ * @param NonMatchingExt Defines how received messages with 29-bit IDs that
+ * do not match any element of the filter list are treated.
+ * This parameter can be a value of @arg FDCAN_Non_Matching_Frames.
+ * @param RejectRemoteStd Filter or reject all the remote 11-bit IDs frames.
+ * This parameter can be a value of @arg FDCAN_Reject_Remote_Frames.
+ * @param RejectRemoteExt Filter or reject all the remote 29-bit IDs frames.
+ * This parameter can be a value of @arg FDCAN_Reject_Remote_Frames.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigGlobalFilter(FDCAN_HandleTypeDef *hfdcan,
+ uint32_t NonMatchingStd,
+ uint32_t NonMatchingExt,
+ uint32_t RejectRemoteStd,
+ uint32_t RejectRemoteExt)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_NON_MATCHING(NonMatchingStd));
+ assert_param(IS_FDCAN_NON_MATCHING(NonMatchingExt));
+ assert_param(IS_FDCAN_REJECT_REMOTE(RejectRemoteStd));
+ assert_param(IS_FDCAN_REJECT_REMOTE(RejectRemoteExt));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Configure global filter */
+ hfdcan->Instance->GFC = ((NonMatchingStd << FDCAN_GFC_ANFS_Pos) |
+ (NonMatchingExt << FDCAN_GFC_ANFE_Pos) |
+ (RejectRemoteStd << FDCAN_GFC_RRFS_Pos) |
+ (RejectRemoteExt << FDCAN_GFC_RRFE_Pos));
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the extended ID mask.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param Mask Extended ID Mask.
+ * This parameter must be a number between 0 and 0x1FFFFFFF
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigExtendedIdMask(FDCAN_HandleTypeDef *hfdcan, uint32_t Mask)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_MAX_VALUE(Mask, 0x1FFFFFFFU));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Configure the extended ID mask */
+ hfdcan->Instance->XIDAM = Mask;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the Rx FIFO operation mode.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param RxFifo Rx FIFO.
+ * This parameter can be one of the following values:
+ * @arg FDCAN_RX_FIFO0: Rx FIFO 0
+ * @arg FDCAN_RX_FIFO1: Rx FIFO 1
+ * @param OperationMode operation mode.
+ * This parameter can be a value of @arg FDCAN_Rx_FIFO_operation_mode.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigRxFifoOverwrite(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo, uint32_t OperationMode)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_RX_FIFO(RxFifo));
+ assert_param(IS_FDCAN_RX_FIFO_MODE(OperationMode));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ if (RxFifo == FDCAN_RX_FIFO0)
+ {
+ /* Select FIFO 0 Operation Mode */
+ MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0OM, OperationMode);
+ }
+ else /* RxFifo == FDCAN_RX_FIFO1 */
+ {
+ /* Select FIFO 1 Operation Mode */
+ MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1OM, OperationMode);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the FIFO watermark.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param FIFO select the FIFO to be configured.
+ * This parameter can be a value of @arg FDCAN_FIFO_watermark.
+ * @param Watermark level for FIFO watermark interrupt.
+ * This parameter must be a number between:
+ * - 0 and 32, if FIFO is FDCAN_CFG_TX_EVENT_FIFO
+ * - 0 and 64, if FIFO is FDCAN_CFG_RX_FIFO0 or FDCAN_CFG_RX_FIFO1
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));
+ if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));
+ }
+ else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Set the level for FIFO watermark interrupt */
+ if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
+ {
+ MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));
+ }
+ else if (FIFO == FDCAN_CFG_RX_FIFO0)
+ {
+ MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));
+ }
+ else /* FIFO == FDCAN_CFG_RX_FIFO1 */
+ {
+ MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the RAM watchdog.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param CounterStartValue Start value of the Message RAM Watchdog Counter,
+ * This parameter must be a number between 0x00 and 0xFF,
+ * with the reset value of 0x00 the counter is disabled.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigRamWatchdog(FDCAN_HandleTypeDef *hfdcan, uint32_t CounterStartValue)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_MAX_VALUE(CounterStartValue, 0xFFU));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Configure the RAM watchdog counter start value */
+ MODIFY_REG(hfdcan->Instance->RWD, FDCAN_RWD_WDC, CounterStartValue);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the timestamp counter.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TimestampPrescaler Timestamp Counter Prescaler.
+ * This parameter can be a value of @arg FDCAN_Timestamp_Prescaler.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigTimestampCounter(FDCAN_HandleTypeDef *hfdcan, uint32_t TimestampPrescaler)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TIMESTAMP_PRESCALER(TimestampPrescaler));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Configure prescaler */
+ MODIFY_REG(hfdcan->Instance->TSCC, FDCAN_TSCC_TCP, TimestampPrescaler);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable the timestamp counter.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TimestampOperation Timestamp counter operation.
+ * This parameter can be a value of @arg FDCAN_Timestamp.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_EnableTimestampCounter(FDCAN_HandleTypeDef *hfdcan, uint32_t TimestampOperation)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TIMESTAMP(TimestampOperation));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Enable timestamp counter */
+ MODIFY_REG(hfdcan->Instance->TSCC, FDCAN_TSCC_TSS, TimestampOperation);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable the timestamp counter.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_DisableTimestampCounter(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Disable timestamp counter */
+ CLEAR_BIT(hfdcan->Instance->TSCC, FDCAN_TSCC_TSS);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get the timestamp counter value.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval Value Timestamp counter value
+ */
+uint16_t HAL_FDCAN_GetTimestampCounter(FDCAN_HandleTypeDef *hfdcan)
+{
+ return (uint16_t)(hfdcan->Instance->TSCV);
+}
+
+/**
+ * @brief Reset the timestamp counter to zero.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ResetTimestampCounter(FDCAN_HandleTypeDef *hfdcan)
+{
+ if ((hfdcan->Instance->TSCC & FDCAN_TSCC_TSS) != FDCAN_TIMESTAMP_EXTERNAL)
+ {
+ /* Reset timestamp counter.
+ Actually any write operation to TSCV clears the counter */
+ CLEAR_REG(hfdcan->Instance->TSCV);
+ }
+ else
+ {
+ /* Update error code.
+ Unable to reset external counter */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the timeout counter.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TimeoutOperation Timeout counter operation.
+ * This parameter can be a value of @arg FDCAN_Timeout_Operation.
+ * @param TimeoutPeriod Start value of the timeout down-counter.
+ * This parameter must be a number between 0x0000 and 0xFFFF
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigTimeoutCounter(FDCAN_HandleTypeDef *hfdcan, uint32_t TimeoutOperation, uint32_t TimeoutPeriod)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TIMEOUT(TimeoutOperation));
+ assert_param(IS_FDCAN_MAX_VALUE(TimeoutPeriod, 0xFFFFU));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Select timeout operation and configure period */
+ MODIFY_REG(hfdcan->Instance->TOCC, (FDCAN_TOCC_TOS | FDCAN_TOCC_TOP), (TimeoutOperation | (TimeoutPeriod << FDCAN_TOCC_TOP_Pos)));
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable the timeout counter.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_EnableTimeoutCounter(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Enable timeout counter */
+ SET_BIT(hfdcan->Instance->TOCC, FDCAN_TOCC_ETOC);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable the timeout counter.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_DisableTimeoutCounter(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Disable timeout counter */
+ CLEAR_BIT(hfdcan->Instance->TOCC, FDCAN_TOCC_ETOC);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get the timeout counter value.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval Value Timeout counter value
+ */
+uint16_t HAL_FDCAN_GetTimeoutCounter(FDCAN_HandleTypeDef *hfdcan)
+{
+ return (uint16_t)(hfdcan->Instance->TOCV);
+}
+
+/**
+ * @brief Reset the timeout counter to its start value.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ResetTimeoutCounter(FDCAN_HandleTypeDef *hfdcan)
+{
+ if ((hfdcan->Instance->TOCC & FDCAN_TOCC_TOS) == FDCAN_TIMEOUT_CONTINUOUS)
+ {
+ /* Reset timeout counter to start value */
+ CLEAR_REG(hfdcan->Instance->TOCV);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code.
+ Unable to reset counter: controlled only by FIFO empty state */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the transmitter delay compensation.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TdcOffset Transmitter Delay Compensation Offset.
+ * This parameter must be a number between 0x00 and 0x7F.
+ * @param TdcFilter Transmitter Delay Compensation Filter Window Length.
+ * This parameter must be a number between 0x00 and 0x7F.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigTxDelayCompensation(FDCAN_HandleTypeDef *hfdcan, uint32_t TdcOffset, uint32_t TdcFilter)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_MAX_VALUE(TdcOffset, 0x7FU));
+ assert_param(IS_FDCAN_MAX_VALUE(TdcFilter, 0x7FU));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Configure TDC offset and filter window */
+ hfdcan->Instance->TDCR = ((TdcFilter << FDCAN_TDCR_TDCF_Pos) | (TdcOffset << FDCAN_TDCR_TDCO_Pos));
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable the transmitter delay compensation.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_EnableTxDelayCompensation(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Enable transmitter delay compensation */
+ SET_BIT(hfdcan->Instance->DBTP, FDCAN_DBTP_TDC);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable the transmitter delay compensation.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_DisableTxDelayCompensation(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Disable transmitter delay compensation */
+ CLEAR_BIT(hfdcan->Instance->DBTP, FDCAN_DBTP_TDC);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable ISO 11898-1 protocol mode.
+ * CAN FD frame format is according to ISO 11898-1 standard.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_EnableISOMode(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Disable Non ISO protocol mode */
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_NISO);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable ISO 11898-1 protocol mode.
+ * CAN FD frame format is according to Bosch CAN FD specification V1.0.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_DisableISOMode(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Enable Non ISO protocol mode */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_NISO);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable edge filtering during bus integration.
+ * Two consecutive dominant tq are required to detect an edge for hard synchronization.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_EnableEdgeFiltering(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Enable edge filtering */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_EFBI);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable edge filtering during bus integration.
+ * One dominant tq is required to detect an edge for hard synchronization.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_DisableEdgeFiltering(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Disable edge filtering */
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_EFBI);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FDCAN_Exported_Functions_Group3 Control functions
+ * @brief Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Control functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) HAL_FDCAN_Start : Start the FDCAN module
+ (+) HAL_FDCAN_Stop : Stop the FDCAN module and enable access to configuration registers
+ (+) HAL_FDCAN_AddMessageToTxFifoQ : Add a message to the Tx FIFO/Queue and activate the corresponding transmission request
+ (+) HAL_FDCAN_AddMessageToTxBuffer : Add a message to a dedicated Tx buffer
+ (+) HAL_FDCAN_EnableTxBufferRequest : Enable transmission request
+ (+) HAL_FDCAN_GetLatestTxFifoQRequestBuffer : Get Tx buffer index of latest Tx FIFO/Queue request
+ (+) HAL_FDCAN_AbortTxRequest : Abort transmission request
+ (+) HAL_FDCAN_GetRxMessage : Get an FDCAN frame from the Rx Buffer/FIFO zone into the message RAM
+ (+) HAL_FDCAN_GetTxEvent : Get an FDCAN Tx event from the Tx Event FIFO zone into the message RAM
+ (+) HAL_FDCAN_GetHighPriorityMessageStatus : Get high priority message status
+ (+) HAL_FDCAN_GetProtocolStatus : Get protocol status
+ (+) HAL_FDCAN_GetErrorCounters : Get error counter values
+ (+) HAL_FDCAN_IsRxBufferMessageAvailable : Check if a new message is received in the selected Rx buffer
+ (+) HAL_FDCAN_IsTxBufferMessagePending : Check if a transmission request is pending on the selected Tx buffer
+ (+) HAL_FDCAN_GetRxFifoFillLevel : Return Rx FIFO fill level
+ (+) HAL_FDCAN_GetTxFifoFreeLevel : Return Tx FIFO free level
+ (+) HAL_FDCAN_IsRestrictedOperationMode : Check if the FDCAN peripheral entered Restricted Operation Mode
+ (+) HAL_FDCAN_ExitRestrictedOperationMode : Exit Restricted Operation Mode
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the FDCAN module.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Change FDCAN peripheral state */
+ hfdcan->State = HAL_FDCAN_STATE_BUSY;
+
+ /* Request leave initialisation */
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
+
+ /* Reset the FDCAN ErrorCode */
+ hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Stop the FDCAN module and enable access to configuration registers.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_Stop(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+
+ if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
+ {
+ /* Request initialisation */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
+
+ /* Wait until the INIT bit into CCCR register is set */
+ while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Reset counter */
+ Counter = 0U;
+
+ /* Exit from Sleep mode */
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
+
+ /* Wait until FDCAN exits sleep mode */
+ while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Enable configuration change */
+ SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);
+
+ /* Reset Latest Tx FIFO/Queue Request Buffer Index */
+ hfdcan->LatestTxFifoQRequest = 0U;
+
+ /* Change FDCAN peripheral state */
+ hfdcan->State = HAL_FDCAN_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Add a message to the Tx FIFO/Queue and activate the corresponding transmission request
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param pTxHeader pointer to a FDCAN_TxHeaderTypeDef structure.
+ * @param pTxData pointer to a buffer containing the payload of the Tx frame.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)
+{
+ uint32_t PutIndex;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
+ if (pTxHeader->IdType == FDCAN_STANDARD_ID)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));
+ }
+ else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));
+ }
+ assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));
+ assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
+ assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));
+ assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
+ assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));
+ assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));
+ assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
+ {
+ /* Check that the Tx FIFO/Queue has an allocated area into the RAM */
+ if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ return HAL_ERROR;
+ }
+
+ /* Check that the Tx FIFO/Queue is not full */
+ if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Retrieve the Tx FIFO PutIndex */
+ PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);
+
+ /* Add the message to the Tx FIFO/Queue */
+ FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);
+
+ /* Activate the corresponding transmission request */
+ hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);
+
+ /* Store the Latest Tx FIFO/Queue Request Buffer Index */
+ hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Add a message to a dedicated Tx buffer
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param pTxHeader pointer to a FDCAN_TxHeaderTypeDef structure.
+ * @param pTxData pointer to a buffer containing the payload of the Tx frame.
+ * @param BufferIndex index of the buffer to be configured.
+ * This parameter can be a value of @arg FDCAN_Tx_location.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxBuffer(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData, uint32_t BufferIndex)
+{
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
+ if (pTxHeader->IdType == FDCAN_STANDARD_ID)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));
+ }
+ else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));
+ }
+ assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));
+ assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
+ assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));
+ assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
+ assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));
+ assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));
+ assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));
+ assert_param(IS_FDCAN_TX_LOCATION(BufferIndex));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Check that the selected buffer has an allocated area into the RAM */
+ if (POSITION_VAL(BufferIndex) >= ((hfdcan->Instance->TXBC & FDCAN_TXBC_NDTB) >> FDCAN_TXBC_NDTB_Pos))
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ return HAL_ERROR;
+ }
+
+ /* Check that there is no transmittion request pending for the selected buffer */
+ if ((hfdcan->Instance->TXBRP & BufferIndex) != 0U)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PENDING;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Add the message to the Tx buffer */
+ FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, POSITION_VAL(BufferIndex));
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable transmission request.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param BufferIndex buffer index.
+ * This parameter can be any combination of @arg FDCAN_Tx_location.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_EnableTxBufferRequest(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndex)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
+ {
+ /* Add transmission request */
+ hfdcan->Instance->TXBAR = BufferIndex;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get Tx buffer index of latest Tx FIFO/Queue request
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval Tx buffer index of last Tx FIFO/Queue request
+ * - Any value of @arg FDCAN_Tx_location if Tx request has been submitted.
+ * - 0 if no Tx FIFO/Queue request have been submitted.
+ */
+uint32_t HAL_FDCAN_GetLatestTxFifoQRequestBuffer(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Return Last Tx FIFO/Queue Request Buffer */
+ return hfdcan->LatestTxFifoQRequest;
+}
+
+/**
+ * @brief Abort transmission request
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param BufferIndex buffer index.
+ * This parameter can be any combination of @arg FDCAN_Tx_location.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_AbortTxRequest(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndex)
+{
+ if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
+ {
+ /* Add cancellation request */
+ hfdcan->Instance->TXBCR = BufferIndex;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get an FDCAN frame from the Rx Buffer/FIFO zone into the message RAM.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param RxLocation Location of the received message to be read.
+ * This parameter can be a value of @arg FDCAN_Rx_location.
+ * @param pRxHeader pointer to a FDCAN_RxHeaderTypeDef structure.
+ * @param pRxData pointer to a buffer where the payload of the Rx frame will be stored.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)
+{
+ uint32_t *RxAddress;
+ uint8_t *pData;
+ uint32_t ByteCounter;
+ uint32_t GetIndex = 0;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ if (state == HAL_FDCAN_STATE_BUSY)
+ {
+ if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */
+ {
+ /* Check that the Rx FIFO 0 has an allocated area into the RAM */
+ if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ return HAL_ERROR;
+ }
+
+ /* Check that the Rx FIFO 0 is not empty */
+ if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Calculate Rx FIFO 0 element address */
+ GetIndex = ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);
+ RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));
+ }
+ }
+ else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
+ {
+ /* Check that the Rx FIFO 1 has an allocated area into the RAM */
+ if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ return HAL_ERROR;
+ }
+
+ /* Check that the Rx FIFO 0 is not empty */
+ if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Calculate Rx FIFO 1 element address */
+ GetIndex = ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);
+ RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));
+ }
+ }
+ else /* Rx element is assigned to a dedicated Rx buffer */
+ {
+ /* Check that the selected buffer has an allocated area into the RAM */
+ if (RxLocation >= hfdcan->Init.RxBuffersNbr)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Calculate Rx buffer address */
+ RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));
+ }
+ }
+
+ /* Retrieve IdType */
+ pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;
+
+ /* Retrieve Identifier */
+ if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */
+ {
+ pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);
+ }
+ else /* Extended ID element */
+ {
+ pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);
+ }
+
+ /* Retrieve RxFrameType */
+ pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);
+
+ /* Retrieve ErrorStateIndicator */
+ pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);
+
+ /* Increment RxAddress pointer to second word of Rx FIFO element */
+ RxAddress++;
+
+ /* Retrieve RxTimestamp */
+ pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);
+
+ /* Retrieve DataLength */
+ pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);
+
+ /* Retrieve BitRateSwitch */
+ pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);
+
+ /* Retrieve FDFormat */
+ pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);
+
+ /* Retrieve FilterIndex */
+ pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);
+
+ /* Retrieve NonMatchingFrame */
+ pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);
+
+ /* Increment RxAddress pointer to payload of Rx FIFO element */
+ RxAddress++;
+
+ /* Retrieve Rx payload */
+ pData = (uint8_t *)RxAddress;
+ for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)
+ {
+ pRxData[ByteCounter] = pData[ByteCounter];
+ }
+
+ if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */
+ {
+ /* Acknowledge the Rx FIFO 0 that the oldest element is read so that it increments the GetIndex */
+ hfdcan->Instance->RXF0A = GetIndex;
+ }
+ else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
+ {
+ /* Acknowledge the Rx FIFO 1 that the oldest element is read so that it increments the GetIndex */
+ hfdcan->Instance->RXF1A = GetIndex;
+ }
+ else /* Rx element is assigned to a dedicated Rx buffer */
+ {
+ /* Clear the New Data flag of the current Rx buffer */
+ if (RxLocation < FDCAN_RX_BUFFER32)
+ {
+ hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);
+ }
+ else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */
+ {
+ hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get an FDCAN Tx event from the Tx Event FIFO zone into the message RAM.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param pTxEvent pointer to a FDCAN_TxEventFifoTypeDef structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_GetTxEvent(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxEventFifoTypeDef *pTxEvent)
+{
+ uint32_t *TxEventAddress;
+ uint32_t GetIndex;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_MIN_VALUE(hfdcan->Init.TxEventsNbr, 1U));
+
+ if (state == HAL_FDCAN_STATE_BUSY)
+ {
+ /* Check that the Tx Event FIFO has an allocated area into the RAM */
+ if ((hfdcan->Instance->TXEFC & FDCAN_TXEFC_EFS) == 0U)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ return HAL_ERROR;
+ }
+
+ /* Check that the Tx event FIFO is not empty */
+ if ((hfdcan->Instance->TXEFS & FDCAN_TXEFS_EFFL) == 0U)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;
+
+ return HAL_ERROR;
+ }
+
+ /* Calculate Tx event FIFO element address */
+ GetIndex = ((hfdcan->Instance->TXEFS & FDCAN_TXEFS_EFGI) >> FDCAN_TXEFS_EFGI_Pos);
+ TxEventAddress = (uint32_t *)(hfdcan->msgRam.TxEventFIFOSA + (GetIndex * 2U * 4U));
+
+ /* Retrieve IdType */
+ pTxEvent->IdType = *TxEventAddress & FDCAN_ELEMENT_MASK_XTD;
+
+ /* Retrieve Identifier */
+ if (pTxEvent->IdType == FDCAN_STANDARD_ID) /* Standard ID element */
+ {
+ pTxEvent->Identifier = ((*TxEventAddress & FDCAN_ELEMENT_MASK_STDID) >> 18U);
+ }
+ else /* Extended ID element */
+ {
+ pTxEvent->Identifier = (*TxEventAddress & FDCAN_ELEMENT_MASK_EXTID);
+ }
+
+ /* Retrieve RxFrameType */
+ pTxEvent->TxFrameType = (*TxEventAddress & FDCAN_ELEMENT_MASK_RTR);
+
+ /* Retrieve ErrorStateIndicator */
+ pTxEvent->ErrorStateIndicator = (*TxEventAddress & FDCAN_ELEMENT_MASK_ESI);
+
+ /* Increment TxEventAddress pointer to second word of Tx Event FIFO element */
+ TxEventAddress++;
+
+ /* Retrieve RxTimestamp */
+ pTxEvent->TxTimestamp = (*TxEventAddress & FDCAN_ELEMENT_MASK_TS);
+
+ /* Retrieve DataLength */
+ pTxEvent->DataLength = (*TxEventAddress & FDCAN_ELEMENT_MASK_DLC);
+
+ /* Retrieve BitRateSwitch */
+ pTxEvent->BitRateSwitch = (*TxEventAddress & FDCAN_ELEMENT_MASK_BRS);
+
+ /* Retrieve FDFormat */
+ pTxEvent->FDFormat = (*TxEventAddress & FDCAN_ELEMENT_MASK_FDF);
+
+ /* Retrieve EventType */
+ pTxEvent->EventType = (*TxEventAddress & FDCAN_ELEMENT_MASK_ET);
+
+ /* Retrieve MessageMarker */
+ pTxEvent->MessageMarker = ((*TxEventAddress & FDCAN_ELEMENT_MASK_MM) >> 24);
+
+ /* Acknowledge the Tx Event FIFO that the oldest element is read so that it increments the GetIndex */
+ hfdcan->Instance->TXEFA = GetIndex;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get high priority message status.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param HpMsgStatus pointer to an FDCAN_HpMsgStatusTypeDef structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_GetHighPriorityMessageStatus(FDCAN_HandleTypeDef *hfdcan, FDCAN_HpMsgStatusTypeDef *HpMsgStatus)
+{
+ HpMsgStatus->FilterList = ((hfdcan->Instance->HPMS & FDCAN_HPMS_FLST) >> FDCAN_HPMS_FLST_Pos);
+ HpMsgStatus->FilterIndex = ((hfdcan->Instance->HPMS & FDCAN_HPMS_FIDX) >> FDCAN_HPMS_FIDX_Pos);
+ HpMsgStatus->MessageStorage = (hfdcan->Instance->HPMS & FDCAN_HPMS_MSI);
+ HpMsgStatus->MessageIndex = (hfdcan->Instance->HPMS & FDCAN_HPMS_BIDX);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Get protocol status.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param ProtocolStatus pointer to an FDCAN_ProtocolStatusTypeDef structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_GetProtocolStatus(FDCAN_HandleTypeDef *hfdcan, FDCAN_ProtocolStatusTypeDef *ProtocolStatus)
+{
+ uint32_t StatusReg;
+
+ /* Read the protocol status register */
+ StatusReg = READ_REG(hfdcan->Instance->PSR);
+
+ /* Fill the protocol status structure */
+ ProtocolStatus->LastErrorCode = (StatusReg & FDCAN_PSR_LEC);
+ ProtocolStatus->DataLastErrorCode = ((StatusReg & FDCAN_PSR_DLEC) >> FDCAN_PSR_DLEC_Pos);
+ ProtocolStatus->Activity = (StatusReg & FDCAN_PSR_ACT);
+ ProtocolStatus->ErrorPassive = ((StatusReg & FDCAN_PSR_EP) >> FDCAN_PSR_EP_Pos);
+ ProtocolStatus->Warning = ((StatusReg & FDCAN_PSR_EW) >> FDCAN_PSR_EW_Pos);
+ ProtocolStatus->BusOff = ((StatusReg & FDCAN_PSR_BO) >> FDCAN_PSR_BO_Pos);
+ ProtocolStatus->RxESIflag = ((StatusReg & FDCAN_PSR_RESI) >> FDCAN_PSR_RESI_Pos);
+ ProtocolStatus->RxBRSflag = ((StatusReg & FDCAN_PSR_RBRS) >> FDCAN_PSR_RBRS_Pos);
+ ProtocolStatus->RxFDFflag = ((StatusReg & FDCAN_PSR_REDL) >> FDCAN_PSR_REDL_Pos);
+ ProtocolStatus->ProtocolException = ((StatusReg & FDCAN_PSR_PXE) >> FDCAN_PSR_PXE_Pos);
+ ProtocolStatus->TDCvalue = ((StatusReg & FDCAN_PSR_TDCV) >> FDCAN_PSR_TDCV_Pos);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Get error counter values.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param ErrorCounters pointer to an FDCAN_ErrorCountersTypeDef structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_GetErrorCounters(FDCAN_HandleTypeDef *hfdcan, FDCAN_ErrorCountersTypeDef *ErrorCounters)
+{
+ uint32_t CountersReg;
+
+ /* Read the error counters register */
+ CountersReg = READ_REG(hfdcan->Instance->ECR);
+
+ /* Fill the error counters structure */
+ ErrorCounters->TxErrorCnt = ((CountersReg & FDCAN_ECR_TEC) >> FDCAN_ECR_TEC_Pos);
+ ErrorCounters->RxErrorCnt = ((CountersReg & FDCAN_ECR_REC) >> FDCAN_ECR_REC_Pos);
+ ErrorCounters->RxErrorPassive = ((CountersReg & FDCAN_ECR_RP) >> FDCAN_ECR_RP_Pos);
+ ErrorCounters->ErrorLogging = ((CountersReg & FDCAN_ECR_CEL) >> FDCAN_ECR_CEL_Pos);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Check if a new message is received in the selected Rx buffer.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param RxBufferIndex Rx buffer index.
+ * This parameter must be a number between 0 and 63.
+ * @retval Status
+ * - 0 : No new message on RxBufferIndex.
+ * - 1 : New message received on RxBufferIndex.
+ */
+uint32_t HAL_FDCAN_IsRxBufferMessageAvailable(FDCAN_HandleTypeDef *hfdcan, uint32_t RxBufferIndex)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_MAX_VALUE(RxBufferIndex, 63U));
+ uint32_t NewData1 = hfdcan->Instance->NDAT1;
+ uint32_t NewData2 = hfdcan->Instance->NDAT2;
+
+ /* Check new message reception on the selected buffer */
+ if (((RxBufferIndex < 32U) && ((NewData1 & (uint32_t)((uint32_t)1 << RxBufferIndex)) == 0U)) ||
+ ((RxBufferIndex >= 32U) && ((NewData2 & (uint32_t)((uint32_t)1 << (RxBufferIndex & 0x1FU))) == 0U)))
+ {
+ return 0;
+ }
+
+ /* Clear the New Data flag of the current Rx buffer */
+ if (RxBufferIndex < 32U)
+ {
+ hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxBufferIndex);
+ }
+ else /* 32 <= RxBufferIndex <= 63 */
+ {
+ hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxBufferIndex & 0x1FU));
+ }
+
+ return 1;
+}
+
+/**
+ * @brief Check if a transmission request is pending on the selected Tx buffer.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TxBufferIndex Tx buffer index.
+ * This parameter can be any combination of @arg FDCAN_Tx_location.
+ * @retval Status
+ * - 0 : No pending transmission request on TxBufferIndex.
+ * - 1 : Pending transmission request on TxBufferIndex.
+ */
+uint32_t HAL_FDCAN_IsTxBufferMessagePending(FDCAN_HandleTypeDef *hfdcan, uint32_t TxBufferIndex)
+{
+ /* Check pending transmittion request on the selected buffer */
+ if ((hfdcan->Instance->TXBRP & TxBufferIndex) == 0U)
+ {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * @brief Return Rx FIFO fill level.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param RxFifo Rx FIFO.
+ * This parameter can be one of the following values:
+ * @arg FDCAN_RX_FIFO0: Rx FIFO 0
+ * @arg FDCAN_RX_FIFO1: Rx FIFO 1
+ * @retval Level Rx FIFO fill level.
+ */
+uint32_t HAL_FDCAN_GetRxFifoFillLevel(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo)
+{
+ uint32_t FillLevel;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_RX_FIFO(RxFifo));
+
+ if (RxFifo == FDCAN_RX_FIFO0)
+ {
+ FillLevel = hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL;
+ }
+ else /* RxFifo == FDCAN_RX_FIFO1 */
+ {
+ FillLevel = hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL;
+ }
+
+ /* Return Rx FIFO fill level */
+ return FillLevel;
+}
+
+/**
+ * @brief Return Tx FIFO free level: number of consecutive free Tx FIFO
+ * elements starting from Tx FIFO GetIndex.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval Level Tx FIFO free level.
+ */
+uint32_t HAL_FDCAN_GetTxFifoFreeLevel(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t FreeLevel;
+
+ FreeLevel = hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFFL;
+
+ /* Return Tx FIFO free level */
+ return FreeLevel;
+}
+
+/**
+ * @brief Check if the FDCAN peripheral entered Restricted Operation Mode.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval Status
+ * - 0 : Normal FDCAN operation.
+ * - 1 : Restricted Operation Mode active.
+ */
+uint32_t HAL_FDCAN_IsRestrictedOperationMode(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t OperationMode;
+
+ /* Get Operation Mode */
+ OperationMode = ((hfdcan->Instance->CCCR & FDCAN_CCCR_ASM) >> FDCAN_CCCR_ASM_Pos);
+
+ return OperationMode;
+}
+
+/**
+ * @brief Exit Restricted Operation Mode.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ExitRestrictedOperationMode(FDCAN_HandleTypeDef *hfdcan)
+{
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Exit Restricted Operation mode */
+ CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FDCAN_Exported_Functions_Group4 TT Configuration and control functions
+ * @brief TT Configuration and control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### TT Configuration and control functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) HAL_FDCAN_TT_ConfigOperation : Initialize TT operation parameters
+ (+) HAL_FDCAN_TT_ConfigReferenceMessage : Configure the reference message
+ (+) HAL_FDCAN_TT_ConfigTrigger : Configure the FDCAN trigger
+ (+) HAL_FDCAN_TT_SetGlobalTime : Schedule global time adjustment
+ (+) HAL_FDCAN_TT_SetClockSynchronization : Schedule TUR numerator update
+ (+) HAL_FDCAN_TT_ConfigStopWatch : Configure stop watch source and polarity
+ (+) HAL_FDCAN_TT_ConfigRegisterTimeMark : Configure register time mark pulse generation
+ (+) HAL_FDCAN_TT_EnableRegisterTimeMarkPulse : Enable register time mark pulse generation
+ (+) HAL_FDCAN_TT_DisableRegisterTimeMarkPulse : Disable register time mark pulse generation
+ (+) HAL_FDCAN_TT_EnableTriggerTimeMarkPulse : Enable trigger time mark pulse generation
+ (+) HAL_FDCAN_TT_DisableTriggerTimeMarkPulse : Disable trigger time mark pulse generation
+ (+) HAL_FDCAN_TT_EnableHardwareGapControl : Enable gap control by input pin fdcan1_evt
+ (+) HAL_FDCAN_TT_DisableHardwareGapControl : Disable gap control by input pin fdcan1_evt
+ (+) HAL_FDCAN_TT_EnableTimeMarkGapControl : Enable gap control (finish only) by register time mark interrupt
+ (+) HAL_FDCAN_TT_DisableTimeMarkGapControl : Disable gap control by register time mark interrupt
+ (+) HAL_FDCAN_TT_SetNextIsGap : Transmit next reference message with Next_is_Gap = "1"
+ (+) HAL_FDCAN_TT_SetEndOfGap : Finish a Gap by requesting start of reference message
+ (+) HAL_FDCAN_TT_ConfigExternalSyncPhase : Configure target phase used for external synchronization
+ (+) HAL_FDCAN_TT_EnableExternalSynchronization : Synchronize the phase of the FDCAN schedule to an external schedule
+ (+) HAL_FDCAN_TT_DisableExternalSynchronization : Disable external schedule synchronization
+ (+) HAL_FDCAN_TT_GetOperationStatus : Get TT operation status
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize TT operation parameters.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param pTTParams pointer to a FDCAN_TT_ConfigTypeDef structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_ConfigOperation(FDCAN_HandleTypeDef *hfdcan, FDCAN_TT_ConfigTypeDef *pTTParams)
+{
+ uint32_t tickstart;
+ uint32_t RAMcounter;
+ uint32_t StartAddress;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_TT_TUR_NUMERATOR(pTTParams->TURNumerator));
+ assert_param(IS_FDCAN_TT_TUR_DENOMINATOR(pTTParams->TURDenominator));
+ assert_param(IS_FDCAN_TT_TIME_MASTER(pTTParams->TimeMaster));
+ assert_param(IS_FDCAN_MAX_VALUE(pTTParams->SyncDevLimit, 7U));
+ assert_param(IS_FDCAN_MAX_VALUE(pTTParams->InitRefTrigOffset, 127U));
+ assert_param(IS_FDCAN_MAX_VALUE(pTTParams->TriggerMemoryNbr, 64U));
+ assert_param(IS_FDCAN_TT_CYCLE_START_SYNC(pTTParams->CycleStartSync));
+ assert_param(IS_FDCAN_TT_STOP_WATCH_TRIGGER(pTTParams->StopWatchTrigSel));
+ assert_param(IS_FDCAN_TT_EVENT_TRIGGER(pTTParams->EventTrigSel));
+ if (pTTParams->TimeMaster == FDCAN_TT_POTENTIAL_MASTER)
+ {
+ assert_param(IS_FDCAN_TT_BASIC_CYCLES_NUMBER(pTTParams->BasicCyclesNbr));
+ }
+ if (pTTParams->OperationMode != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ assert_param(IS_FDCAN_TT_OPERATION(pTTParams->GapEnable));
+ assert_param(IS_FDCAN_MAX_VALUE(pTTParams->AppWdgLimit, 255U));
+ assert_param(IS_FDCAN_TT_EVENT_TRIGGER_POLARITY(pTTParams->EvtTrigPolarity));
+ assert_param(IS_FDCAN_TT_TX_ENABLE_WINDOW(pTTParams->TxEnableWindow));
+ assert_param(IS_FDCAN_MAX_VALUE(pTTParams->ExpTxTrigNbr, 4095U));
+ }
+ if (pTTParams->OperationMode != FDCAN_TT_COMMUNICATION_LEVEL1)
+ {
+ assert_param(IS_FDCAN_TT_TUR_LEVEL_0_2(pTTParams->TURNumerator, pTTParams->TURDenominator));
+ assert_param(IS_FDCAN_TT_EXTERNAL_CLK_SYNC(pTTParams->ExternalClkSync));
+ assert_param(IS_FDCAN_TT_GLOBAL_TIME_FILTERING(pTTParams->GlobalTimeFilter));
+ assert_param(IS_FDCAN_TT_AUTO_CLK_CALIBRATION(pTTParams->ClockCalibration));
+ }
+ else
+ {
+ assert_param(IS_FDCAN_TT_TUR_LEVEL_1(pTTParams->TURNumerator, pTTParams->TURDenominator));
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Stop local time in order to enable write access to the other bits of TURCF register */
+ CLEAR_BIT(hfdcan->ttcan->TURCF, FDCAN_TURCF_ELT);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until the ELT bit into TURCF register is reset */
+ while ((hfdcan->ttcan->TURCF & FDCAN_TURCF_ELT) != 0U)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Configure TUR (Time Unit Ratio) */
+ MODIFY_REG(hfdcan->ttcan->TURCF,
+ (FDCAN_TURCF_NCL | FDCAN_TURCF_DC),
+ (((pTTParams->TURNumerator - 0x10000U) << FDCAN_TURCF_NCL_Pos) | (pTTParams->TURDenominator << FDCAN_TURCF_DC_Pos)));
+
+ /* Enable local time */
+ SET_BIT(hfdcan->ttcan->TURCF, FDCAN_TURCF_ELT);
+
+ /* Configure TT operation */
+ MODIFY_REG(hfdcan->ttcan->TTOCF,
+ (FDCAN_TTOCF_OM | FDCAN_TTOCF_TM | FDCAN_TTOCF_LDSDL | FDCAN_TTOCF_IRTO),
+ (pTTParams->OperationMode | \
+ pTTParams->TimeMaster | \
+ (pTTParams->SyncDevLimit << FDCAN_TTOCF_LDSDL_Pos) | \
+ (pTTParams->InitRefTrigOffset << FDCAN_TTOCF_IRTO_Pos)));
+ if (pTTParams->OperationMode != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ MODIFY_REG(hfdcan->ttcan->TTOCF,
+ (FDCAN_TTOCF_GEN | FDCAN_TTOCF_AWL | FDCAN_TTOCF_EVTP),
+ (pTTParams->GapEnable | \
+ (pTTParams->AppWdgLimit << FDCAN_TTOCF_AWL_Pos) | \
+ pTTParams->EvtTrigPolarity));
+ }
+ if (pTTParams->OperationMode != FDCAN_TT_COMMUNICATION_LEVEL1)
+ {
+ MODIFY_REG(hfdcan->ttcan->TTOCF,
+ (FDCAN_TTOCF_EECS | FDCAN_TTOCF_EGTF | FDCAN_TTOCF_ECC),
+ (pTTParams->ExternalClkSync | \
+ pTTParams->GlobalTimeFilter | \
+ pTTParams->ClockCalibration));
+ }
+
+ /* Configure system matrix limits */
+ MODIFY_REG(hfdcan->ttcan->TTMLM, FDCAN_TTMLM_CSS, pTTParams->CycleStartSync);
+ if (pTTParams->OperationMode != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ MODIFY_REG(hfdcan->ttcan->TTMLM,
+ (FDCAN_TTMLM_TXEW | FDCAN_TTMLM_ENTT),
+ (((pTTParams->TxEnableWindow - 1U) << FDCAN_TTMLM_TXEW_Pos) | (pTTParams->ExpTxTrigNbr << FDCAN_TTMLM_ENTT_Pos)));
+ }
+ if (pTTParams->TimeMaster == FDCAN_TT_POTENTIAL_MASTER)
+ {
+ MODIFY_REG(hfdcan->ttcan->TTMLM, FDCAN_TTMLM_CCM, pTTParams->BasicCyclesNbr);
+ }
+
+ /* Configure input triggers: Stop watch and Event */
+ MODIFY_REG(hfdcan->ttcan->TTTS,
+ (FDCAN_TTTS_SWTSEL | FDCAN_TTTS_EVTSEL),
+ (pTTParams->StopWatchTrigSel | pTTParams->EventTrigSel));
+
+ /* Configure trigger memory start address */
+ StartAddress = (hfdcan->msgRam.EndAddress - SRAMCAN_BASE) / 4U;
+ MODIFY_REG(hfdcan->ttcan->TTTMC, FDCAN_TTTMC_TMSA, (StartAddress << FDCAN_TTTMC_TMSA_Pos));
+
+ /* Trigger memory elements number */
+ MODIFY_REG(hfdcan->ttcan->TTTMC, FDCAN_TTTMC_TME, (pTTParams->TriggerMemoryNbr << FDCAN_TTTMC_TME_Pos));
+
+ /* Recalculate End Address */
+ hfdcan->msgRam.TTMemorySA = hfdcan->msgRam.EndAddress;
+ hfdcan->msgRam.EndAddress = hfdcan->msgRam.TTMemorySA + (pTTParams->TriggerMemoryNbr * 2U * 4U);
+
+ if (hfdcan->msgRam.EndAddress > FDCAN_MESSAGE_RAM_END_ADDRESS) /* Last address of the Message RAM */
+ {
+ /* Update error code.
+ Message RAM overflow */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Flush the allocated Message RAM area */
+ for (RAMcounter = hfdcan->msgRam.TTMemorySA; RAMcounter < hfdcan->msgRam.EndAddress; RAMcounter += 4U)
+ {
+ *(uint32_t *)(RAMcounter) = 0x00000000;
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the reference message.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param IdType Identifier Type.
+ * This parameter can be a value of @arg FDCAN_id_type.
+ * @param Identifier Reference Identifier.
+ * This parameter must be a number between:
+ * - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
+ * - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID
+ * @param Payload Enable or disable the additional payload.
+ * This parameter can be a value of @arg FDCAN_TT_Reference_Message_Payload.
+ * This parameter is ignored in case of time slaves.
+ * If this parameter is set to FDCAN_TT_REF_MESSAGE_ADD_PAYLOAD, the
+ * following elements are taken from Tx Buffer 0:
+ * - MessageMarker
+ * - TxEventFifoControl
+ * - DataLength
+ * - Data Bytes (payload):
+ * - bytes 2-8, for Level 1
+ * - bytes 5-8, for Level 0 and Level 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_ConfigReferenceMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t IdType, uint32_t Identifier, uint32_t Payload)
+{
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_ID_TYPE(IdType));
+ if (IdType == FDCAN_STANDARD_ID)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(Identifier, 0x7FFU));
+ }
+ else /* IdType == FDCAN_EXTENDED_ID */
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(Identifier, 0x1FFFFFFFU));
+ }
+ assert_param(IS_FDCAN_TT_REFERENCE_MESSAGE_PAYLOAD(Payload));
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Configure reference message identifier type, identifier and payload */
+ if (IdType == FDCAN_EXTENDED_ID)
+ {
+ MODIFY_REG(hfdcan->ttcan->TTRMC, (FDCAN_TTRMC_RID | FDCAN_TTRMC_XTD | FDCAN_TTRMC_RMPS), (Payload | IdType | Identifier));
+ }
+ else /* IdType == FDCAN_STANDARD_ID */
+ {
+ MODIFY_REG(hfdcan->ttcan->TTRMC, (FDCAN_TTRMC_RID | FDCAN_TTRMC_XTD | FDCAN_TTRMC_RMPS), (Payload | IdType | (Identifier << 18)));
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the FDCAN trigger according to the specified
+ * parameters in the FDCAN_TriggerTypeDef structure.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param sTriggerConfig pointer to an FDCAN_TriggerTypeDef structure that
+ * contains the trigger configuration information
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_ConfigTrigger(FDCAN_HandleTypeDef *hfdcan, FDCAN_TriggerTypeDef *sTriggerConfig)
+{
+ uint32_t CycleCode;
+ uint32_t MessageNumber;
+ uint32_t TriggerElementW1;
+ uint32_t TriggerElementW2;
+ uint32_t *TriggerAddress;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_MAX_VALUE(sTriggerConfig->TriggerIndex, 63U));
+ assert_param(IS_FDCAN_MAX_VALUE(sTriggerConfig->TimeMark, 0xFFFFU));
+ assert_param(IS_FDCAN_TT_REPEAT_FACTOR(sTriggerConfig->RepeatFactor));
+ if (sTriggerConfig->RepeatFactor != FDCAN_TT_REPEAT_EVERY_CYCLE)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(sTriggerConfig->StartCycle, (sTriggerConfig->RepeatFactor - 1U)));
+ }
+ assert_param(IS_FDCAN_TT_TM_EVENT_INTERNAL(sTriggerConfig->TmEventInt));
+ assert_param(IS_FDCAN_TT_TM_EVENT_EXTERNAL(sTriggerConfig->TmEventExt));
+ assert_param(IS_FDCAN_TT_TRIGGER_TYPE(sTriggerConfig->TriggerType));
+ assert_param(IS_FDCAN_ID_TYPE(sTriggerConfig->FilterType));
+ if ((sTriggerConfig->TriggerType == FDCAN_TT_TX_TRIGGER_SINGLE) ||
+ (sTriggerConfig->TriggerType == FDCAN_TT_TX_TRIGGER_CONTINUOUS) ||
+ (sTriggerConfig->TriggerType == FDCAN_TT_TX_TRIGGER_ARBITRATION) ||
+ (sTriggerConfig->TriggerType == FDCAN_TT_TX_TRIGGER_MERGED))
+ {
+ assert_param(IS_FDCAN_TX_LOCATION(sTriggerConfig->TxBufferIndex));
+ }
+ if (sTriggerConfig->TriggerType == FDCAN_TT_RX_TRIGGER)
+ {
+ if (sTriggerConfig->FilterType == FDCAN_STANDARD_ID)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(sTriggerConfig->FilterIndex, 63U));
+ }
+ else /* sTriggerConfig->FilterType == FDCAN_EXTENDED_ID */
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(sTriggerConfig->FilterIndex, 127U));
+ }
+ }
+
+ if (hfdcan->State == HAL_FDCAN_STATE_READY)
+ {
+ /* Calculate cycle code */
+ if (sTriggerConfig->RepeatFactor == FDCAN_TT_REPEAT_EVERY_CYCLE)
+ {
+ CycleCode = FDCAN_TT_REPEAT_EVERY_CYCLE;
+ }
+ else /* sTriggerConfig->RepeatFactor != FDCAN_TT_REPEAT_EVERY_CYCLE */
+ {
+ CycleCode = sTriggerConfig->RepeatFactor + sTriggerConfig->StartCycle;
+ }
+
+ /* Build first word of trigger element */
+ TriggerElementW1 = ((sTriggerConfig->TimeMark << 16) | \
+ (CycleCode << 8) | \
+ sTriggerConfig->TmEventInt | \
+ sTriggerConfig->TmEventExt | \
+ sTriggerConfig->TriggerType);
+
+ /* Select message number depending on trigger type (transmission or reception) */
+ if (sTriggerConfig->TriggerType == FDCAN_TT_RX_TRIGGER)
+ {
+ MessageNumber = sTriggerConfig->FilterIndex;
+ }
+ else if ((sTriggerConfig->TriggerType == FDCAN_TT_TX_TRIGGER_SINGLE) ||
+ (sTriggerConfig->TriggerType == FDCAN_TT_TX_TRIGGER_CONTINUOUS) ||
+ (sTriggerConfig->TriggerType == FDCAN_TT_TX_TRIGGER_ARBITRATION) ||
+ (sTriggerConfig->TriggerType == FDCAN_TT_TX_TRIGGER_MERGED))
+ {
+ MessageNumber = POSITION_VAL(sTriggerConfig->TxBufferIndex);
+ }
+ else
+ {
+ MessageNumber = 0U;
+ }
+
+ /* Build second word of trigger element */
+ TriggerElementW2 = ((sTriggerConfig->FilterType >> 7) | (MessageNumber << 16));
+
+ /* Calculate trigger address */
+ TriggerAddress = (uint32_t *)(hfdcan->msgRam.TTMemorySA + (sTriggerConfig->TriggerIndex * 4U * 2U));
+
+ /* Write trigger element to the message RAM */
+ *TriggerAddress = TriggerElementW1;
+ TriggerAddress++;
+ *TriggerAddress = TriggerElementW2;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Schedule global time adjustment for the next reference message.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TimePreset time preset value.
+ * This parameter must be a number between:
+ * - 0x0000 and 0x7FFF, Next_Master_Ref_Mark = Current_Master_Ref_Mark + TimePreset
+ * or
+ * - 0x8001 and 0xFFFF, Next_Master_Ref_Mark = Current_Master_Ref_Mark - (0x10000 - TimePreset)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_SetGlobalTime(FDCAN_HandleTypeDef *hfdcan, uint32_t TimePreset)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_TT_TIME_PRESET(TimePreset));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Check that the external clock synchronization is enabled */
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_EECS) != FDCAN_TTOCF_EECS)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+
+ /* Check that no global time preset is pending */
+ if ((hfdcan->ttcan->TTOST & FDCAN_TTOST_WGTD) == FDCAN_TTOST_WGTD)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PENDING;
+
+ return HAL_ERROR;
+ }
+
+ /* Configure time preset */
+ MODIFY_REG(hfdcan->ttcan->TTGTP, FDCAN_TTGTP_TP, (TimePreset << FDCAN_TTGTP_TP_Pos));
+
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Schedule time preset to take effect by the next reference message */
+ SET_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_SGT);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Schedule TUR numerator update for the next reference message.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param NewTURNumerator new value of the TUR numerator.
+ * This parameter must be a number between 0x10000 and 0x1FFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_SetClockSynchronization(FDCAN_HandleTypeDef *hfdcan, uint32_t NewTURNumerator)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_TT_TUR_NUMERATOR(NewTURNumerator));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Check that the external clock synchronization is enabled */
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_EECS) != FDCAN_TTOCF_EECS)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+
+ /* Check that no external clock synchronization is pending */
+ if ((hfdcan->ttcan->TTOST & FDCAN_TTOST_WECS) == FDCAN_TTOST_WECS)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PENDING;
+
+ return HAL_ERROR;
+ }
+
+ /* Configure new TUR numerator */
+ MODIFY_REG(hfdcan->ttcan->TURCF, FDCAN_TURCF_NCL, (NewTURNumerator - 0x10000U));
+
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Schedule TUR numerator update by the next reference message */
+ SET_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_ECS);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure stop watch source and polarity.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param Source stop watch source.
+ * This parameter can be a value of @arg FDCAN_TT_stop_watch_source.
+ * @param Polarity stop watch polarity.
+ * This parameter can be a value of @arg FDCAN_TT_stop_watch_polarity.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_ConfigStopWatch(FDCAN_HandleTypeDef *hfdcan, uint32_t Source, uint32_t Polarity)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_TT_STOP_WATCH_SOURCE(Source));
+ assert_param(IS_FDCAN_TT_STOP_WATCH_POLARITY(Polarity));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Select stop watch source and polarity */
+ MODIFY_REG(hfdcan->ttcan->TTOCN, (FDCAN_TTOCN_SWS | FDCAN_TTOCN_SWP), (Source | Polarity));
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure register time mark pulse generation.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TimeMarkSource time mark source.
+ * This parameter can be a value of @arg FDCAN_TT_time_mark_source.
+ * @param TimeMarkValue time mark value (reference).
+ * This parameter must be a number between 0 and 0xFFFF.
+ * @param RepeatFactor repeat factor of the cycle for which the time mark is valid.
+ * This parameter can be a value of @arg FDCAN_TT_Repeat_Factor.
+ * @param StartCycle index of the first cycle in which the time mark becomes valid.
+ * This parameter is ignored if RepeatFactor is set to FDCAN_TT_REPEAT_EVERY_CYCLE.
+ * This parameter must be a number between 0 and RepeatFactor.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_ConfigRegisterTimeMark(FDCAN_HandleTypeDef *hfdcan,
+ uint32_t TimeMarkSource, uint32_t TimeMarkValue,
+ uint32_t RepeatFactor, uint32_t StartCycle)
+{
+ uint32_t Counter = 0U;
+ uint32_t CycleCode;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_TT_REGISTER_TIME_MARK_SOURCE(TimeMarkSource));
+ assert_param(IS_FDCAN_MAX_VALUE(TimeMarkValue, 0xFFFFU));
+ assert_param(IS_FDCAN_TT_REPEAT_FACTOR(RepeatFactor));
+ if (RepeatFactor != FDCAN_TT_REPEAT_EVERY_CYCLE)
+ {
+ assert_param(IS_FDCAN_MAX_VALUE(StartCycle, (RepeatFactor - 1U)));
+ }
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Disable the time mark compare function */
+ CLEAR_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_TMC);
+
+ if (TimeMarkSource != FDCAN_TT_REG_TIMEMARK_DIABLED)
+ {
+ /* Calculate cycle code */
+ if (RepeatFactor == FDCAN_TT_REPEAT_EVERY_CYCLE)
+ {
+ CycleCode = FDCAN_TT_REPEAT_EVERY_CYCLE;
+ }
+ else /* RepeatFactor != FDCAN_TT_REPEAT_EVERY_CYCLE */
+ {
+ CycleCode = RepeatFactor + StartCycle;
+ }
+
+ Counter = 0U;
+
+ /* Wait until the LCKM bit into TTTMK register is reset */
+ while ((hfdcan->ttcan->TTTMK & FDCAN_TTTMK_LCKM) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Configure time mark value and cycle code */
+ hfdcan->ttcan->TTTMK = ((TimeMarkValue << FDCAN_TTTMK_TM_Pos) | (CycleCode << FDCAN_TTTMK_TICC_Pos));
+
+ Counter = 0U;
+
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Update the register time mark compare source */
+ MODIFY_REG(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_TMC, TimeMarkSource);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable register time mark pulse generation.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_EnableRegisterTimeMarkPulse(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Enable Register Time Mark Interrupt output on fdcan1_rtp */
+ SET_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_RTIE);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable register time mark pulse generation.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_DisableRegisterTimeMarkPulse(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Disable Register Time Mark Interrupt output on fdcan1_rtp */
+ CLEAR_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_RTIE);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable trigger time mark pulse generation.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_EnableTriggerTimeMarkPulse(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_OM) != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Enable Trigger Time Mark Interrupt output on fdcan1_tmp */
+ SET_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_TTIE);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code.
+ Feature not supported for TT Level 0 */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable trigger time mark pulse generation.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_DisableTriggerTimeMarkPulse(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_OM) != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Disable Trigger Time Mark Interrupt output on fdcan1_rtp */
+ CLEAR_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_TTIE);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code.
+ Feature not supported for TT Level 0 */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable gap control by input pin fdcan1_evt.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_EnableHardwareGapControl(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_OM) != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Enable gap control by pin fdcan1_evt */
+ SET_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_GCS);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code.
+ Feature not supported for TT Level 0 */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable gap control by input pin fdcan1_evt.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_DisableHardwareGapControl(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_OM) != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Disable gap control by pin fdcan1_evt */
+ CLEAR_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_GCS);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code.
+ Feature not supported for TT Level 0 */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable gap control (finish only) by register time mark interrupt.
+ * The next register time mark interrupt (TTIR.RTMI = "1") will finish
+ * the Gap and start the reference message.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_EnableTimeMarkGapControl(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_OM) != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Enable gap control by register time mark interrupt */
+ SET_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_TMG);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code.
+ Feature not supported for TT Level 0 */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable gap control by register time mark interrupt.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_DisableTimeMarkGapControl(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_OM) != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Disable gap control by register time mark interrupt */
+ CLEAR_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_TMG);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code.
+ Feature not supported for TT Level 0 */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Transmit next reference message with Next_is_Gap = "1".
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_SetNextIsGap(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Check that the node is configured for external event-synchronized TT operation */
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_GEN) != FDCAN_TTOCF_GEN)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_OM) != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Set Next is Gap */
+ SET_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_NIG);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code.
+ Feature not supported for TT Level 0 */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Finish a Gap by requesting start of reference message.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_SetEndOfGap(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Check that the node is configured for external event-synchronized TT operation */
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_GEN) != FDCAN_TTOCF_GEN)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_OM) != FDCAN_TT_COMMUNICATION_LEVEL0)
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Set Finish Gap */
+ SET_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_FGP);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code.
+ Feature not supported for TT Level 0 */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_SUPPORTED;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure target phase used for external synchronization by event
+ * trigger input pin fdcan1_evt.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TargetPhase defines target value of cycle time when a rising edge
+ * of fdcan1_evt is expected.
+ * This parameter must be a number between 0 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_ConfigExternalSyncPhase(FDCAN_HandleTypeDef *hfdcan, uint32_t TargetPhase)
+{
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_MAX_VALUE(TargetPhase, 0xFFFFU));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Check that no external schedule synchronization is pending */
+ if ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_ESCN) == FDCAN_TTOCN_ESCN)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PENDING;
+
+ return HAL_ERROR;
+ }
+
+ /* Configure cycle time target phase */
+ MODIFY_REG(hfdcan->ttcan->TTGTP, FDCAN_TTGTP_CTP, (TargetPhase << FDCAN_TTGTP_CTP_Pos));
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Synchronize the phase of the FDCAN schedule to an external schedule
+ * using event trigger input pin fdcan1_evt.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_EnableExternalSynchronization(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Enable external synchronization */
+ SET_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_ESCN);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable external schedule synchronization.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_DisableExternalSynchronization(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t Counter = 0U;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Wait until the LCKC bit into TTOCN register is reset */
+ while ((hfdcan->ttcan->TTOCN & FDCAN_TTOCN_LCKC) != 0U)
+ {
+ /* Check for the Timeout */
+ if (Counter > FDCAN_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ /* Increment counter */
+ Counter++;
+ }
+
+ /* Disable external synchronization */
+ CLEAR_BIT(hfdcan->ttcan->TTOCN, FDCAN_TTOCN_ESCN);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Get TT operation status.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TTOpStatus pointer to an FDCAN_TTOperationStatusTypeDef structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_GetOperationStatus(FDCAN_HandleTypeDef *hfdcan, FDCAN_TTOperationStatusTypeDef *TTOpStatus)
+{
+ uint32_t TTStatusReg;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+
+ /* Read the TT operation status register */
+ TTStatusReg = READ_REG(hfdcan->ttcan->TTOST);
+
+ /* Fill the TT operation status structure */
+ TTOpStatus->ErrorLevel = (TTStatusReg & FDCAN_TTOST_EL);
+ TTOpStatus->MasterState = (TTStatusReg & FDCAN_TTOST_MS);
+ TTOpStatus->SyncState = (TTStatusReg & FDCAN_TTOST_SYS);
+ TTOpStatus->GTimeQuality = ((TTStatusReg & FDCAN_TTOST_QGTP) >> FDCAN_TTOST_QGTP_Pos);
+ TTOpStatus->ClockQuality = ((TTStatusReg & FDCAN_TTOST_QCS) >> FDCAN_TTOST_QCS_Pos);
+ TTOpStatus->RefTrigOffset = ((TTStatusReg & FDCAN_TTOST_RTO) >> FDCAN_TTOST_RTO_Pos);
+ TTOpStatus->GTimeDiscPending = ((TTStatusReg & FDCAN_TTOST_WGTD) >> FDCAN_TTOST_WGTD_Pos);
+ TTOpStatus->GapFinished = ((TTStatusReg & FDCAN_TTOST_GFI) >> FDCAN_TTOST_GFI_Pos);
+ TTOpStatus->MasterPriority = ((TTStatusReg & FDCAN_TTOST_TMP) >> FDCAN_TTOST_TMP_Pos);
+ TTOpStatus->GapStarted = ((TTStatusReg & FDCAN_TTOST_GSI) >> FDCAN_TTOST_GSI_Pos);
+ TTOpStatus->WaitForEvt = ((TTStatusReg & FDCAN_TTOST_WFE) >> FDCAN_TTOST_WFE_Pos);
+ TTOpStatus->AppWdgEvt = ((TTStatusReg & FDCAN_TTOST_AWE) >> FDCAN_TTOST_AWE_Pos);
+ TTOpStatus->ECSPending = ((TTStatusReg & FDCAN_TTOST_WECS) >> FDCAN_TTOST_WECS_Pos);
+ TTOpStatus->PhaseLock = ((TTStatusReg & FDCAN_TTOST_SPL) >> FDCAN_TTOST_SPL_Pos);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FDCAN_Exported_Functions_Group5 Interrupts management
+ * @brief Interrupts management
+ *
+@verbatim
+ ==============================================================================
+ ##### Interrupts management #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) HAL_FDCAN_ConfigInterruptLines : Assign interrupts to either Interrupt line 0 or 1
+ (+) HAL_FDCAN_TT_ConfigInterruptLines : Assign TT interrupts to either Interrupt line 0 or 1
+ (+) HAL_FDCAN_ActivateNotification : Enable interrupts
+ (+) HAL_FDCAN_DeactivateNotification : Disable interrupts
+ (+) HAL_FDCAN_TT_ActivateNotification : Enable TT interrupts
+ (+) HAL_FDCAN_TT_DeactivateNotification : Disable TT interrupts
+ (+) HAL_FDCAN_IRQHandler : Handles FDCAN interrupt request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Assign interrupts to either Interrupt line 0 or 1.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param ITList indicates which interrupts will be assigned to the selected interrupt line.
+ * This parameter can be any combination of @arg FDCAN_Interrupts.
+ * @param InterruptLine Interrupt line.
+ * This parameter can be a value of @arg FDCAN_Interrupt_Line.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ConfigInterruptLines(FDCAN_HandleTypeDef *hfdcan, uint32_t ITList, uint32_t InterruptLine)
+{
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_IT(ITList));
+ assert_param(IS_FDCAN_IT_LINE(InterruptLine));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Assign list of interrupts to the selected line */
+ if (InterruptLine == FDCAN_INTERRUPT_LINE0)
+ {
+ CLEAR_BIT(hfdcan->Instance->ILS, ITList);
+ }
+ else /* InterruptLine == FDCAN_INTERRUPT_LINE1 */
+ {
+ SET_BIT(hfdcan->Instance->ILS, ITList);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Assign TT interrupts to either Interrupt line 0 or 1.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TTITList indicates which interrupts will be assigned to the selected interrupt line.
+ * This parameter can be any combination of @arg FDCAN_TTInterrupts.
+ * @param InterruptLine Interrupt line.
+ * This parameter can be a value of @arg FDCAN_Interrupt_Line.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_ConfigInterruptLines(FDCAN_HandleTypeDef *hfdcan, uint32_t TTITList, uint32_t InterruptLine)
+{
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_TT_IT(TTITList));
+ assert_param(IS_FDCAN_IT_LINE(InterruptLine));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Assign list of interrupts to the selected line */
+ if (InterruptLine == FDCAN_INTERRUPT_LINE0)
+ {
+ CLEAR_BIT(hfdcan->ttcan->TTILS, TTITList);
+ }
+ else /* InterruptLine == FDCAN_INTERRUPT_LINE1 */
+ {
+ SET_BIT(hfdcan->ttcan->TTILS, TTITList);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable interrupts.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param ActiveITs indicates which interrupts will be enabled.
+ * This parameter can be any combination of @arg FDCAN_Interrupts.
+ * @param BufferIndexes Tx Buffer Indexes.
+ * This parameter can be any combination of @arg FDCAN_Tx_location.
+ * This parameter is ignored if ActiveITs does not include one of the following:
+ * - FDCAN_IT_TX_COMPLETE
+ * - FDCAN_IT_TX_ABORT_COMPLETE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes)
+{
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_IT(ActiveITs));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Enable Interrupt lines */
+ if ((ActiveITs & hfdcan->Instance->ILS) == 0U)
+ {
+ /* Enable Interrupt line 0 */
+ SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
+ }
+ else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)
+ {
+ /* Enable Interrupt line 1 */
+ SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
+ }
+ else
+ {
+ /* Enable Interrupt lines 0 and 1 */
+ hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);
+ }
+
+ if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)
+ {
+ /* Enable Tx Buffer Transmission Interrupt to set TC flag in IR register,
+ but interrupt will only occure if TC is enabled in IE register */
+ SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);
+ }
+
+ if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)
+ {
+ /* Enable Tx Buffer Cancellation Finished Interrupt to set TCF flag in IR register,
+ but interrupt will only occure if TCF is enabled in IE register */
+ SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);
+ }
+
+ /* Enable the selected interrupts */
+ __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable interrupts.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param InactiveITs indicates which interrupts will be disabled.
+ * This parameter can be any combination of @arg FDCAN_Interrupts.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_DeactivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t InactiveITs)
+{
+ uint32_t ITLineSelection;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_IT(InactiveITs));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Disable the selected interrupts */
+ __HAL_FDCAN_DISABLE_IT(hfdcan, InactiveITs);
+
+ if ((InactiveITs & FDCAN_IT_TX_COMPLETE) != 0U)
+ {
+ /* Disable Tx Buffer Transmission Interrupts */
+ CLEAR_REG(hfdcan->Instance->TXBTIE);
+ }
+
+ if ((InactiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)
+ {
+ /* Disable Tx Buffer Cancellation Finished Interrupt */
+ CLEAR_REG(hfdcan->Instance->TXBCIE);
+ }
+
+ ITLineSelection = hfdcan->Instance->ILS;
+
+ if ((hfdcan->Instance->IE | ITLineSelection) == ITLineSelection)
+ {
+ /* Disable Interrupt line 0 */
+ CLEAR_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
+ }
+
+ if ((hfdcan->Instance->IE & ITLineSelection) == 0U)
+ {
+ /* Disable Interrupt line 1 */
+ CLEAR_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable TT interrupts.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param ActiveTTITs indicates which TT interrupts will be enabled.
+ * This parameter can be any combination of @arg FDCAN_TTInterrupts.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveTTITs)
+{
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_TT_IT(ActiveTTITs));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Enable Interrupt lines */
+ if ((ActiveTTITs & hfdcan->ttcan->TTILS) == 0U)
+ {
+ /* Enable Interrupt line 0 */
+ SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
+ }
+ else if ((ActiveTTITs & hfdcan->ttcan->TTILS) == ActiveTTITs)
+ {
+ /* Enable Interrupt line 1 */
+ SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
+ }
+ else
+ {
+ /* Enable Interrupt lines 0 and 1 */
+ hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);
+ }
+
+ /* Enable the selected TT interrupts */
+ __HAL_FDCAN_TT_ENABLE_IT(hfdcan, ActiveTTITs);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable TT interrupts.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param InactiveTTITs indicates which TT interrupts will be disabled.
+ * This parameter can be any combination of @arg FDCAN_TTInterrupts.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_FDCAN_TT_DeactivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t InactiveTTITs)
+{
+ uint32_t ITLineSelection;
+ HAL_FDCAN_StateTypeDef state = hfdcan->State;
+
+ /* Check function parameters */
+ assert_param(IS_FDCAN_TT_INSTANCE(hfdcan->Instance));
+ assert_param(IS_FDCAN_TT_IT(InactiveTTITs));
+
+ if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ {
+ /* Disable the selected TT interrupts */
+ __HAL_FDCAN_TT_DISABLE_IT(hfdcan, InactiveTTITs);
+
+ ITLineSelection = hfdcan->ttcan->TTILS;
+
+ if ((hfdcan->ttcan->TTIE | ITLineSelection) == ITLineSelection)
+ {
+ /* Disable Interrupt line 0 */
+ CLEAR_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
+ }
+
+ if ((hfdcan->ttcan->TTIE & ITLineSelection) == 0U)
+ {
+ /* Disable Interrupt line 1 */
+ CLEAR_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Handles FDCAN interrupt request.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+void HAL_FDCAN_IRQHandler(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t ClkCalibrationITs;
+ uint32_t TxEventFifoITs;
+ uint32_t RxFifo0ITs;
+ uint32_t RxFifo1ITs;
+ uint32_t Errors;
+ uint32_t ErrorStatusITs;
+ uint32_t TransmittedBuffers;
+ uint32_t AbortedBuffers;
+ uint32_t TTSchedSyncITs;
+ uint32_t TTTimeMarkITs;
+ uint32_t TTGlobTimeITs;
+ uint32_t TTDistErrors;
+ uint32_t TTFatalErrors;
+ uint32_t SWTime;
+ uint32_t SWCycleCount;
+
+ ClkCalibrationITs = (FDCAN_CCU->IR << 30);
+ ClkCalibrationITs &= (FDCAN_CCU->IE << 30);
+ TxEventFifoITs = hfdcan->Instance->IR & FDCAN_TX_EVENT_FIFO_MASK;
+ TxEventFifoITs &= hfdcan->Instance->IE;
+ RxFifo0ITs = hfdcan->Instance->IR & FDCAN_RX_FIFO0_MASK;
+ RxFifo0ITs &= hfdcan->Instance->IE;
+ RxFifo1ITs = hfdcan->Instance->IR & FDCAN_RX_FIFO1_MASK;
+ RxFifo1ITs &= hfdcan->Instance->IE;
+ Errors = hfdcan->Instance->IR & FDCAN_ERROR_MASK;
+ Errors &= hfdcan->Instance->IE;
+ ErrorStatusITs = hfdcan->Instance->IR & FDCAN_ERROR_STATUS_MASK;
+ ErrorStatusITs &= hfdcan->Instance->IE;
+
+ /* High Priority Message interrupt management *******************************/
+ if (__HAL_FDCAN_GET_IT_SOURCE(hfdcan, FDCAN_IT_RX_HIGH_PRIORITY_MSG) != 0U)
+ {
+ if (__HAL_FDCAN_GET_FLAG(hfdcan, FDCAN_FLAG_RX_HIGH_PRIORITY_MSG) != 0U)
+ {
+ /* Clear the High Priority Message flag */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_RX_HIGH_PRIORITY_MSG);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->HighPriorityMessageCallback(hfdcan);
+#else
+ /* High Priority Message Callback */
+ HAL_FDCAN_HighPriorityMessageCallback(hfdcan);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Transmission Abort interrupt management **********************************/
+ if (__HAL_FDCAN_GET_IT_SOURCE(hfdcan, FDCAN_IT_TX_ABORT_COMPLETE) != 0U)
+ {
+ if (__HAL_FDCAN_GET_FLAG(hfdcan, FDCAN_FLAG_TX_ABORT_COMPLETE) != 0U)
+ {
+ /* List of aborted monitored buffers */
+ AbortedBuffers = hfdcan->Instance->TXBCF;
+ AbortedBuffers &= hfdcan->Instance->TXBCIE;
+
+ /* Clear the Transmission Cancellation flag */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_TX_ABORT_COMPLETE);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TxBufferAbortCallback(hfdcan, AbortedBuffers);
+#else
+ /* Transmission Cancellation Callback */
+ HAL_FDCAN_TxBufferAbortCallback(hfdcan, AbortedBuffers);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Clock calibration unit interrupts management *****************************/
+ if (ClkCalibrationITs != 0U)
+ {
+ /* Clear the Clock Calibration flags */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, ClkCalibrationITs);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->ClockCalibrationCallback(hfdcan, ClkCalibrationITs);
+#else
+ /* Clock Calibration Callback */
+ HAL_FDCAN_ClockCalibrationCallback(hfdcan, ClkCalibrationITs);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+
+ /* Tx event FIFO interrupts management **************************************/
+ if (TxEventFifoITs != 0U)
+ {
+ /* Clear the Tx Event FIFO flags */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, TxEventFifoITs);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TxEventFifoCallback(hfdcan, TxEventFifoITs);
+#else
+ /* Tx Event FIFO Callback */
+ HAL_FDCAN_TxEventFifoCallback(hfdcan, TxEventFifoITs);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+
+ /* Rx FIFO 0 interrupts management ******************************************/
+ if (RxFifo0ITs != 0U)
+ {
+ /* Clear the Rx FIFO 0 flags */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, RxFifo0ITs);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->RxFifo0Callback(hfdcan, RxFifo0ITs);
+#else
+ /* Rx FIFO 0 Callback */
+ HAL_FDCAN_RxFifo0Callback(hfdcan, RxFifo0ITs);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+
+ /* Rx FIFO 1 interrupts management ******************************************/
+ if (RxFifo1ITs != 0U)
+ {
+ /* Clear the Rx FIFO 1 flags */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, RxFifo1ITs);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->RxFifo1Callback(hfdcan, RxFifo1ITs);
+#else
+ /* Rx FIFO 1 Callback */
+ HAL_FDCAN_RxFifo1Callback(hfdcan, RxFifo1ITs);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+
+ /* Tx FIFO empty interrupt management ***************************************/
+ if (__HAL_FDCAN_GET_IT_SOURCE(hfdcan, FDCAN_IT_TX_FIFO_EMPTY) != 0U)
+ {
+ if (__HAL_FDCAN_GET_FLAG(hfdcan, FDCAN_FLAG_TX_FIFO_EMPTY) != 0U)
+ {
+ /* Clear the Tx FIFO empty flag */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_TX_FIFO_EMPTY);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TxFifoEmptyCallback(hfdcan);
+#else
+ /* Tx FIFO empty Callback */
+ HAL_FDCAN_TxFifoEmptyCallback(hfdcan);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Transmission Complete interrupt management *******************************/
+ if (__HAL_FDCAN_GET_IT_SOURCE(hfdcan, FDCAN_IT_TX_COMPLETE) != 0U)
+ {
+ if (__HAL_FDCAN_GET_FLAG(hfdcan, FDCAN_FLAG_TX_COMPLETE) != 0U)
+ {
+ /* List of transmitted monitored buffers */
+ TransmittedBuffers = hfdcan->Instance->TXBTO;
+ TransmittedBuffers &= hfdcan->Instance->TXBTIE;
+
+ /* Clear the Transmission Complete flag */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_TX_COMPLETE);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TxBufferCompleteCallback(hfdcan, TransmittedBuffers);
+#else
+ /* Transmission Complete Callback */
+ HAL_FDCAN_TxBufferCompleteCallback(hfdcan, TransmittedBuffers);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Rx Buffer New Message interrupt management *******************************/
+ if (__HAL_FDCAN_GET_IT_SOURCE(hfdcan, FDCAN_IT_RX_BUFFER_NEW_MESSAGE) != 0U)
+ {
+ if (__HAL_FDCAN_GET_FLAG(hfdcan, FDCAN_FLAG_RX_BUFFER_NEW_MESSAGE) != 0U)
+ {
+ /* Clear the Rx Buffer New Message flag */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_RX_BUFFER_NEW_MESSAGE);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->RxBufferNewMessageCallback(hfdcan);
+#else
+ /* Rx Buffer New Message Callback */
+ HAL_FDCAN_RxBufferNewMessageCallback(hfdcan);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timestamp Wraparound interrupt management ********************************/
+ if (__HAL_FDCAN_GET_IT_SOURCE(hfdcan, FDCAN_IT_TIMESTAMP_WRAPAROUND) != 0U)
+ {
+ if (__HAL_FDCAN_GET_FLAG(hfdcan, FDCAN_FLAG_TIMESTAMP_WRAPAROUND) != 0U)
+ {
+ /* Clear the Timestamp Wraparound flag */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_TIMESTAMP_WRAPAROUND);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TimestampWraparoundCallback(hfdcan);
+#else
+ /* Timestamp Wraparound Callback */
+ HAL_FDCAN_TimestampWraparoundCallback(hfdcan);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timeout Occurred interrupt management ************************************/
+ if (__HAL_FDCAN_GET_IT_SOURCE(hfdcan, FDCAN_IT_TIMEOUT_OCCURRED) != 0U)
+ {
+ if (__HAL_FDCAN_GET_FLAG(hfdcan, FDCAN_FLAG_TIMEOUT_OCCURRED) != 0U)
+ {
+ /* Clear the Timeout Occurred flag */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_TIMEOUT_OCCURRED);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TimeoutOccurredCallback(hfdcan);
+#else
+ /* Timeout Occurred Callback */
+ HAL_FDCAN_TimeoutOccurredCallback(hfdcan);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Message RAM access failure interrupt management **************************/
+ if (__HAL_FDCAN_GET_IT_SOURCE(hfdcan, FDCAN_IT_RAM_ACCESS_FAILURE) != 0U)
+ {
+ if (__HAL_FDCAN_GET_FLAG(hfdcan, FDCAN_FLAG_RAM_ACCESS_FAILURE) != 0U)
+ {
+ /* Clear the Message RAM access failure flag */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_RAM_ACCESS_FAILURE);
+
+ /* Update error code */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_RAM_ACCESS;
+ }
+ }
+
+ /* Error Status interrupts management ***************************************/
+ if (ErrorStatusITs != 0U)
+ {
+ /* Clear the Error flags */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, ErrorStatusITs);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->ErrorStatusCallback(hfdcan, ErrorStatusITs);
+#else
+ /* Error Status Callback */
+ HAL_FDCAN_ErrorStatusCallback(hfdcan, ErrorStatusITs);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+
+ /* Error interrupts management **********************************************/
+ if (Errors != 0U)
+ {
+ /* Clear the Error flags */
+ __HAL_FDCAN_CLEAR_FLAG(hfdcan, Errors);
+
+ /* Update error code */
+ hfdcan->ErrorCode |= Errors;
+ }
+
+ if (hfdcan->Instance == FDCAN1)
+ {
+ if ((hfdcan->ttcan->TTOCF & FDCAN_TTOCF_OM) != 0U)
+ {
+ TTSchedSyncITs = hfdcan->ttcan->TTIR & FDCAN_TT_SCHEDULE_SYNC_MASK;
+ TTSchedSyncITs &= hfdcan->ttcan->TTIE;
+ TTTimeMarkITs = hfdcan->ttcan->TTIR & FDCAN_TT_TIME_MARK_MASK;
+ TTTimeMarkITs &= hfdcan->ttcan->TTIE;
+ TTGlobTimeITs = hfdcan->ttcan->TTIR & FDCAN_TT_GLOBAL_TIME_MASK;
+ TTGlobTimeITs &= hfdcan->ttcan->TTIE;
+ TTDistErrors = hfdcan->ttcan->TTIR & FDCAN_TT_DISTURBING_ERROR_MASK;
+ TTDistErrors &= hfdcan->ttcan->TTIE;
+ TTFatalErrors = hfdcan->ttcan->TTIR & FDCAN_TT_FATAL_ERROR_MASK;
+ TTFatalErrors &= hfdcan->ttcan->TTIE;
+
+ /* TT Schedule Synchronization interrupts management **********************/
+ if (TTSchedSyncITs != 0U)
+ {
+ /* Clear the TT Schedule Synchronization flags */
+ __HAL_FDCAN_TT_CLEAR_FLAG(hfdcan, TTSchedSyncITs);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TT_ScheduleSyncCallback(hfdcan, TTSchedSyncITs);
+#else
+ /* TT Schedule Synchronization Callback */
+ HAL_FDCAN_TT_ScheduleSyncCallback(hfdcan, TTSchedSyncITs);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+
+ /* TT Time Mark interrupts management *************************************/
+ if (TTTimeMarkITs != 0U)
+ {
+ /* Clear the TT Time Mark flags */
+ __HAL_FDCAN_TT_CLEAR_FLAG(hfdcan, TTTimeMarkITs);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TT_TimeMarkCallback(hfdcan, TTTimeMarkITs);
+#else
+ /* TT Time Mark Callback */
+ HAL_FDCAN_TT_TimeMarkCallback(hfdcan, TTTimeMarkITs);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+
+ /* TT Stop Watch interrupt management *************************************/
+ if (__HAL_FDCAN_TT_GET_IT_SOURCE(hfdcan, FDCAN_TT_IT_STOP_WATCH) != 0U)
+ {
+ if (__HAL_FDCAN_TT_GET_FLAG(hfdcan, FDCAN_TT_FLAG_STOP_WATCH) != 0U)
+ {
+ /* Retrieve Stop watch Time and Cycle count */
+ SWTime = ((hfdcan->ttcan->TTCPT & FDCAN_TTCPT_SWV) >> FDCAN_TTCPT_SWV_Pos);
+ SWCycleCount = ((hfdcan->ttcan->TTCPT & FDCAN_TTCPT_CCV) >> FDCAN_TTCPT_CCV_Pos);
+
+ /* Clear the TT Stop Watch flag */
+ __HAL_FDCAN_TT_CLEAR_FLAG(hfdcan, FDCAN_TT_FLAG_STOP_WATCH);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TT_StopWatchCallback(hfdcan, SWTime, SWCycleCount);
+#else
+ /* TT Stop Watch Callback */
+ HAL_FDCAN_TT_StopWatchCallback(hfdcan, SWTime, SWCycleCount);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* TT Global Time interrupts management ***********************************/
+ if (TTGlobTimeITs != 0U)
+ {
+ /* Clear the TT Global Time flags */
+ __HAL_FDCAN_TT_CLEAR_FLAG(hfdcan, TTGlobTimeITs);
+
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->TT_GlobalTimeCallback(hfdcan, TTGlobTimeITs);
+#else
+ /* TT Global Time Callback */
+ HAL_FDCAN_TT_GlobalTimeCallback(hfdcan, TTGlobTimeITs);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+
+ /* TT Disturbing Error interrupts management ******************************/
+ if (TTDistErrors != 0U)
+ {
+ /* Clear the TT Disturbing Error flags */
+ __HAL_FDCAN_TT_CLEAR_FLAG(hfdcan, TTDistErrors);
+
+ /* Update error code */
+ hfdcan->ErrorCode |= TTDistErrors;
+ }
+
+ /* TT Fatal Error interrupts management ***********************************/
+ if (TTFatalErrors != 0U)
+ {
+ /* Clear the TT Fatal Error flags */
+ __HAL_FDCAN_TT_CLEAR_FLAG(hfdcan, TTFatalErrors);
+
+ /* Update error code */
+ hfdcan->ErrorCode |= TTFatalErrors;
+ }
+ }
+ }
+
+ if (hfdcan->ErrorCode != HAL_FDCAN_ERROR_NONE)
+ {
+#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
+ /* Call registered callback*/
+ hfdcan->ErrorCallback(hfdcan);
+#else
+ /* Error Callback */
+ HAL_FDCAN_ErrorCallback(hfdcan);
+#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FDCAN_Exported_Functions_Group6 Callback functions
+ * @brief FDCAN Callback functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Callback functions #####
+ ==============================================================================
+ [..]
+ This subsection provides the following callback functions:
+ (+) HAL_FDCAN_ClockCalibrationCallback
+ (+) HAL_FDCAN_TxEventFifoCallback
+ (+) HAL_FDCAN_RxFifo0Callback
+ (+) HAL_FDCAN_RxFifo1Callback
+ (+) HAL_FDCAN_TxFifoEmptyCallback
+ (+) HAL_FDCAN_TxBufferCompleteCallback
+ (+) HAL_FDCAN_TxBufferAbortCallback
+ (+) HAL_FDCAN_RxBufferNewMessageCallback
+ (+) HAL_FDCAN_HighPriorityMessageCallback
+ (+) HAL_FDCAN_TimestampWraparoundCallback
+ (+) HAL_FDCAN_TimeoutOccurredCallback
+ (+) HAL_FDCAN_ErrorCallback
+ (+) HAL_FDCAN_ErrorStatusCallback
+ (+) HAL_FDCAN_TT_ScheduleSyncCallback
+ (+) HAL_FDCAN_TT_TimeMarkCallback
+ (+) HAL_FDCAN_TT_StopWatchCallback
+ (+) HAL_FDCAN_TT_GlobalTimeCallback
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Clock Calibration callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param ClkCalibrationITs indicates which Clock Calibration interrupts are signaled.
+ * This parameter can be any combination of @arg FDCAN_Clock_Calibration_Interrupts.
+ * @retval None
+ */
+__weak void HAL_FDCAN_ClockCalibrationCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(ClkCalibrationITs);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_ClockCalibrationCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Event callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TxEventFifoITs indicates which Tx Event FIFO interrupts are signaled.
+ * This parameter can be any combination of @arg FDCAN_Tx_Event_Fifo_Interrupts.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TxEventFifoCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(TxEventFifoITs);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TxEventFifoCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx FIFO 0 callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param RxFifo0ITs indicates which Rx FIFO 0 interrupts are signaled.
+ * This parameter can be any combination of @arg FDCAN_Rx_Fifo0_Interrupts.
+ * @retval None
+ */
+__weak void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(RxFifo0ITs);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_RxFifo0Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx FIFO 1 callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param RxFifo1ITs indicates which Rx FIFO 1 interrupts are signaled.
+ * This parameter can be any combination of @arg FDCAN_Rx_Fifo1_Interrupts.
+ * @retval None
+ */
+__weak void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(RxFifo1ITs);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_RxFifo1Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx FIFO Empty callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TxFifoEmptyCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Transmission Complete callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param BufferIndexes Indexes of the transmitted buffers.
+ * This parameter can be any combination of @arg FDCAN_Tx_location.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(BufferIndexes);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TxBufferCompleteCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Transmission Cancellation callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param BufferIndexes Indexes of the aborted buffers.
+ * This parameter can be any combination of @arg FDCAN_Tx_location.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TxBufferAbortCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(BufferIndexes);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TxBufferAbortCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Buffer New Message callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval None
+ */
+__weak void HAL_FDCAN_RxBufferNewMessageCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_RxBufferNewMessageCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Timestamp Wraparound callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TimestampWraparoundCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TimestampWraparoundCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Timeout Occurred callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TimeoutOccurredCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TimeoutOccurredCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief High Priority Message callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval None
+ */
+__weak void HAL_FDCAN_HighPriorityMessageCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_HighPriorityMessageCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Error callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval None
+ */
+__weak void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Error status callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param ErrorStatusITs indicates which Error Status interrupts are signaled.
+ * This parameter can be any combination of @arg FDCAN_Error_Status_Interrupts.
+ * @retval None
+ */
+__weak void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(ErrorStatusITs);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_ErrorStatusCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief TT Schedule Synchronization callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TTSchedSyncITs indicates which TT Schedule Synchronization interrupts are signaled.
+ * This parameter can be any combination of @arg FDCAN_TTScheduleSynchronization_Interrupts.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TT_ScheduleSyncCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(TTSchedSyncITs);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TT_ScheduleSyncCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief TT Time Mark callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TTTimeMarkITs indicates which TT Schedule Synchronization interrupts are signaled.
+ * This parameter can be any combination of @arg FDCAN_TTTimeMark_Interrupts.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TT_TimeMarkCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(TTTimeMarkITs);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TT_TimeMarkCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief TT Stop Watch callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param SWTime Time Value captured at the Stop Watch Trigger pin (fdcan1_swt) falling/rising
+ * edge (as configured via HAL_FDCAN_TTConfigStopWatch).
+ * This parameter is a number between 0 and 0xFFFF.
+ * @param SWCycleCount Cycle count value captured together with SWTime.
+ * This parameter is a number between 0 and 0x3F.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TT_StopWatchCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(SWTime);
+ UNUSED(SWCycleCount);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TT_StopWatchCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief TT Global Time callback.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param TTGlobTimeITs indicates which TT Global Time interrupts are signaled.
+ * This parameter can be any combination of @arg FDCAN_TTGlobalTime_Interrupts.
+ * @retval None
+ */
+__weak void HAL_FDCAN_TT_GlobalTimeCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hfdcan);
+ UNUSED(TTGlobTimeITs);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FDCAN_TT_GlobalTimeCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FDCAN_Exported_Functions_Group7 Peripheral State functions
+ * @brief FDCAN Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State functions #####
+ ==============================================================================
+ [..]
+ This subsection provides functions allowing to :
+ (+) HAL_FDCAN_GetState() : Return the FDCAN state.
+ (+) HAL_FDCAN_GetError() : Return the FDCAN error code if any.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Return the FDCAN state
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL state
+ */
+HAL_FDCAN_StateTypeDef HAL_FDCAN_GetState(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Return FDCAN state */
+ return hfdcan->State;
+}
+
+/**
+ * @brief Return the FDCAN error code
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval FDCAN Error Code
+ */
+uint32_t HAL_FDCAN_GetError(FDCAN_HandleTypeDef *hfdcan)
+{
+ /* Return FDCAN error code */
+ return hfdcan->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup FDCAN_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Calculate each RAM block start address and size
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef FDCAN_CalcultateRamBlockAddresses(FDCAN_HandleTypeDef *hfdcan)
+{
+ uint32_t RAMcounter;
+ uint32_t StartAddress;
+
+ StartAddress = hfdcan->Init.MessageRAMOffset;
+
+ /* Standard filter list start address */
+ MODIFY_REG(hfdcan->Instance->SIDFC, FDCAN_SIDFC_FLSSA, (StartAddress << FDCAN_SIDFC_FLSSA_Pos));
+
+ /* Standard filter elements number */
+ MODIFY_REG(hfdcan->Instance->SIDFC, FDCAN_SIDFC_LSS, (hfdcan->Init.StdFiltersNbr << FDCAN_SIDFC_LSS_Pos));
+
+ /* Extended filter list start address */
+ StartAddress += hfdcan->Init.StdFiltersNbr;
+ MODIFY_REG(hfdcan->Instance->XIDFC, FDCAN_XIDFC_FLESA, (StartAddress << FDCAN_XIDFC_FLESA_Pos));
+
+ /* Extended filter elements number */
+ MODIFY_REG(hfdcan->Instance->XIDFC, FDCAN_XIDFC_LSE, (hfdcan->Init.ExtFiltersNbr << FDCAN_XIDFC_LSE_Pos));
+
+ /* Rx FIFO 0 start address */
+ StartAddress += (hfdcan->Init.ExtFiltersNbr * 2U);
+ MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0SA, (StartAddress << FDCAN_RXF0C_F0SA_Pos));
+
+ /* Rx FIFO 0 elements number */
+ MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0S, (hfdcan->Init.RxFifo0ElmtsNbr << FDCAN_RXF0C_F0S_Pos));
+
+ /* Rx FIFO 1 start address */
+ StartAddress += (hfdcan->Init.RxFifo0ElmtsNbr * hfdcan->Init.RxFifo0ElmtSize);
+ MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1SA, (StartAddress << FDCAN_RXF1C_F1SA_Pos));
+
+ /* Rx FIFO 1 elements number */
+ MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1S, (hfdcan->Init.RxFifo1ElmtsNbr << FDCAN_RXF1C_F1S_Pos));
+
+ /* Rx buffer list start address */
+ StartAddress += (hfdcan->Init.RxFifo1ElmtsNbr * hfdcan->Init.RxFifo1ElmtSize);
+ MODIFY_REG(hfdcan->Instance->RXBC, FDCAN_RXBC_RBSA, (StartAddress << FDCAN_RXBC_RBSA_Pos));
+
+ /* Tx event FIFO start address */
+ StartAddress += (hfdcan->Init.RxBuffersNbr * hfdcan->Init.RxBufferSize);
+ MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFSA, (StartAddress << FDCAN_TXEFC_EFSA_Pos));
+
+ /* Tx event FIFO elements number */
+ MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFS, (hfdcan->Init.TxEventsNbr << FDCAN_TXEFC_EFS_Pos));
+
+ /* Tx buffer list start address */
+ StartAddress += (hfdcan->Init.TxEventsNbr * 2U);
+ MODIFY_REG(hfdcan->Instance->TXBC, FDCAN_TXBC_TBSA, (StartAddress << FDCAN_TXBC_TBSA_Pos));
+
+ /* Dedicated Tx buffers number */
+ MODIFY_REG(hfdcan->Instance->TXBC, FDCAN_TXBC_NDTB, (hfdcan->Init.TxBuffersNbr << FDCAN_TXBC_NDTB_Pos));
+
+ /* Tx FIFO/queue elements number */
+ MODIFY_REG(hfdcan->Instance->TXBC, FDCAN_TXBC_TFQS, (hfdcan->Init.TxFifoQueueElmtsNbr << FDCAN_TXBC_TFQS_Pos));
+
+ hfdcan->msgRam.StandardFilterSA = SRAMCAN_BASE + (hfdcan->Init.MessageRAMOffset * 4U);
+ hfdcan->msgRam.ExtendedFilterSA = hfdcan->msgRam.StandardFilterSA + (hfdcan->Init.StdFiltersNbr * 4U);
+ hfdcan->msgRam.RxFIFO0SA = hfdcan->msgRam.ExtendedFilterSA + (hfdcan->Init.ExtFiltersNbr * 2U * 4U);
+ hfdcan->msgRam.RxFIFO1SA = hfdcan->msgRam.RxFIFO0SA + (hfdcan->Init.RxFifo0ElmtsNbr * hfdcan->Init.RxFifo0ElmtSize * 4U);
+ hfdcan->msgRam.RxBufferSA = hfdcan->msgRam.RxFIFO1SA + (hfdcan->Init.RxFifo1ElmtsNbr * hfdcan->Init.RxFifo1ElmtSize * 4U);
+ hfdcan->msgRam.TxEventFIFOSA = hfdcan->msgRam.RxBufferSA + (hfdcan->Init.RxBuffersNbr * hfdcan->Init.RxBufferSize * 4U);
+ hfdcan->msgRam.TxBufferSA = hfdcan->msgRam.TxEventFIFOSA + (hfdcan->Init.TxEventsNbr * 2U * 4U);
+ hfdcan->msgRam.TxFIFOQSA = hfdcan->msgRam.TxBufferSA + (hfdcan->Init.TxBuffersNbr * hfdcan->Init.TxElmtSize * 4U);
+
+ hfdcan->msgRam.EndAddress = hfdcan->msgRam.TxFIFOQSA + (hfdcan->Init.TxFifoQueueElmtsNbr * hfdcan->Init.TxElmtSize * 4U);
+
+ if (hfdcan->msgRam.EndAddress > FDCAN_MESSAGE_RAM_END_ADDRESS) /* Last address of the Message RAM */
+ {
+ /* Update error code.
+ Message RAM overflow */
+ hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
+
+ /* Change FDCAN state */
+ hfdcan->State = HAL_FDCAN_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Flush the allocated Message RAM area */
+ for (RAMcounter = hfdcan->msgRam.StandardFilterSA; RAMcounter < hfdcan->msgRam.EndAddress; RAMcounter += 4U)
+ {
+ *(uint32_t *)(RAMcounter) = 0x00000000;
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Copy Tx message to the message RAM.
+ * @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
+ * the configuration information for the specified FDCAN.
+ * @param pTxHeader pointer to a FDCAN_TxHeaderTypeDef structure.
+ * @param pTxData pointer to a buffer containing the payload of the Tx frame.
+ * @param BufferIndex index of the buffer to be configured.
+ * @retval HAL status
+ */
+static void FDCAN_CopyMessageToRAM(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData, uint32_t BufferIndex)
+{
+ uint32_t TxElementW1;
+ uint32_t TxElementW2;
+ uint32_t *TxAddress;
+ uint32_t ByteCounter;
+
+ /* Build first word of Tx header element */
+ if (pTxHeader->IdType == FDCAN_STANDARD_ID)
+ {
+ TxElementW1 = (pTxHeader->ErrorStateIndicator |
+ FDCAN_STANDARD_ID |
+ pTxHeader->TxFrameType |
+ (pTxHeader->Identifier << 18));
+ }
+ else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */
+ {
+ TxElementW1 = (pTxHeader->ErrorStateIndicator |
+ FDCAN_EXTENDED_ID |
+ pTxHeader->TxFrameType |
+ pTxHeader->Identifier);
+ }
+
+ /* Build second word of Tx header element */
+ TxElementW2 = ((pTxHeader->MessageMarker << 24) |
+ pTxHeader->TxEventFifoControl |
+ pTxHeader->FDFormat |
+ pTxHeader->BitRateSwitch |
+ pTxHeader->DataLength);
+
+ /* Calculate Tx element address */
+ TxAddress = (uint32_t *)(hfdcan->msgRam.TxBufferSA + (BufferIndex * hfdcan->Init.TxElmtSize * 4U));
+
+ /* Write Tx element header to the message RAM */
+ *TxAddress = TxElementW1;
+ TxAddress++;
+ *TxAddress = TxElementW2;
+ TxAddress++;
+
+ /* Write Tx payload to the message RAM */
+ for (ByteCounter = 0; ByteCounter < DLCtoBytes[pTxHeader->DataLength >> 16]; ByteCounter += 4U)
+ {
+ *TxAddress = (((uint32_t)pTxData[ByteCounter + 3U] << 24) |
+ ((uint32_t)pTxData[ByteCounter + 2U] << 16) |
+ ((uint32_t)pTxData[ByteCounter + 1U] << 8) |
+ (uint32_t)pTxData[ByteCounter]);
+ TxAddress++;
+ }
+}
+
+/**
+ * @}
+ */
+#endif /* HAL_FDCAN_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_flash.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_flash.c
new file mode 100644
index 0000000000..3a6b651fdc
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_flash.c
@@ -0,0 +1,1099 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 ---------------------------------------------------------*/
+FLASH_ProcessTypeDef pFlash;
+/* 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 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.
+ * @param DataAddress specifies the address of data to be programmed
+ *
+ * @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;
+ }
+ else
+ {
+ bank = FLASH_BANK_2;
+ }
+
+ /* 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(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);
+ }
+
+ __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 (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);
+ }
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Program flash words of 256 bits 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.
+ * @param DataAddress specifies the address of data (256 bits) to be programmed
+ *
+ * @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;
+ }
+ else
+ {
+ bank = FLASH_BANK_2;
+ }
+
+ /* 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(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 */
+ }
+
+ __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);
+ }
+ }
+ }
+
+ /* 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);
+ }
+ }
+ }
+
+ /* 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);
+ }
+
+ /* 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(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);
+
+ /* 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);
+#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);
+
+ /* 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 /* 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(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;
+ }
+ }
+
+ 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;
+ }
+
+ /* 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;
+ }
+
+ 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;
+ }
+ else if (FLASH_CRC_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ 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, errorflag;
+ 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_QW_BANK1;
+ }
+ else
+ {
+ bsyflag = FLASH_FLAG_QW_BANK2;
+ }
+
+ 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;
+ }
+ else
+ {
+ errorflag = (FLASH->SR2 & FLASH_FLAG_ALL_ERRORS_BANK2) | 0x80000000U;
+ }
+
+ /* In case of error reported in Flash SR1 or SR2 registers (ECCC not managed as an error) */
+ if((errorflag & 0x7DFFFFFFU) != 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);
+ }
+ }
+ 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);
+ }
+ }
+
+ 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;
+ }
+ }
+ 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;
+ }
+ }
+
+ /* If there is no error flag set */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_flash_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_flash_ex.c
new file mode 100644
index 0000000000..77b809f76b
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_flash_ex.c
@@ -0,0 +1,1709 @@
+/**
+ ******************************************************************************
+ * @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
+ (+) 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
+
+ (#) 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
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 */
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+/** @defgroup FLASHEx_Exported_Functions FLASHEx Exported Functions
+ * @{
+ */
+
+/** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions
+ * @brief Extended IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended programming operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the Extension FLASH
+ programming operations Operations.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Perform a mass erase or erase the specified FLASH memory sectors
+ * @param[in] pEraseInit pointer to an FLASH_EraseInitTypeDef structure that
+ * contains the configuration information for the erasing.
+ *
+ * @param[out] SectorError pointer to variable that contains the configuration
+ * information on faulty sector in case of error (0xFFFFFFFF means that all
+ * the sectors have been correctly erased)
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError)
+{
+ HAL_StatusTypeDef status = HAL_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;
+ }
+ }
+
+ /* 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;
+ }
+ }
+
+ 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 */
+ 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((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);
+ }
+ }
+ 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((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));
+ }
+
+ 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.
+ *
+ * @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 */
+ 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((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 (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((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 */
+ }
+
+ if(pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
+ {
+ /*Mass erase to be done*/
+ if(pEraseInit->Banks == FLASH_BANK_1)
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_MASSERASE_BANK1;
+ }
+ else if(pEraseInit->Banks == FLASH_BANK_2)
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_MASSERASE_BANK2;
+ }
+ else
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_ALLBANK_MASSERASE;
+ }
+
+ FLASH_MassErase(pEraseInit->VoltageRange, pEraseInit->Banks);
+ }
+ else
+ {
+ /* Erase by sector to be done */
+ if(pEraseInit->Banks == FLASH_BANK_1)
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_SECTERASE_BANK1;
+ }
+ else
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_SECTERASE_BANK2;
+ }
+
+ 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_OBInitStruct 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;
+ }
+ else if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ 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 */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Get the Option byte configuration
+ * @param pOBInit pointer to an FLASH_OBInitStruct structure that
+ * contains the configuration information for the programming.
+ * @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 ((pOBInit->Banks == FLASH_BANK_1) || (pOBInit->Banks == FLASH_BANK_2))
+ {
+ 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 */
+}
+
+/**
+ * @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;
+}
+
+/**
+ * @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;
+}
+
+/*
+ * @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 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);
+ }
+ 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 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);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* 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));
+
+ /* 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
+ {
+ /* 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((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);
+ }
+ }
+}
+
+/**
+ * @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((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 */
+ }
+}
+
+/**
+ * @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((Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ /* Enable Write Protection for bank 2 */
+ FLASH->WPSN_PRG2 &= (~(WRPSector & FLASH_WPSN_WRPSN));
+ }
+}
+
+/**
+ * @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((Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ /* Disable Write Protection for bank 2 */
+ FLASH->WPSN_PRG2 |= (WRPSector & FLASH_WPSN_WRPSN);
+ }
+}
+
+/**
+ * @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_BOTH) == FLASH_BANK_1)
+ {
+ regvalue = FLASH->WPSN_CUR1;
+ }
+
+ if((Bank & FLASH_BANK_BOTH) == FLASH_BANK_2)
+ {
+ regvalue = FLASH->WPSN_CUR2;
+ }
+
+ (*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;
+ }
+
+ 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 /* DUAL_CORE */
+ 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;
+ }
+
+ 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((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;
+ }
+}
+
+/**
+ * @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_BOTH) == FLASH_BANK_1)
+ {
+ regvalue = FLASH->PRAR_CUR1;
+ bankBase = FLASH_BANK1_BASE;
+ }
+
+ if((Bank & FLASH_BANK_BOTH) == FLASH_BANK_2)
+ {
+ regvalue = FLASH->PRAR_CUR2;
+ bankBase = FLASH_BANK2_BASE;
+ }
+
+ (*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((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);
+ }
+}
+
+/**
+ * @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_BOTH) == FLASH_BANK_1)
+ {
+ regvalue = FLASH->SCAR_CUR1;
+ bankBase = FLASH_BANK1_BASE;
+ }
+
+ if((Bank & FLASH_BANK_BOTH) == FLASH_BANK_2)
+ {
+ regvalue = FLASH->SCAR_CUR2;
+ bankBase = FLASH_BANK2_BASE;
+ }
+
+ /* 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;
+ }
+ 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;
+ }
+}
+
+/**
+ * @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;
+ }
+ 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;
+ }
+}
+/**
+ * @}
+ */
+
+#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 */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_gfxmmu.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_gfxmmu.c
new file mode 100644
index 0000000000..b873c73bfd
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_gfxmmu.c
@@ -0,0 +1,893 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_gfxmmu.c
+ * @author MCD Application Team
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Graphic MMU (GFXMMU) peripheral:
+ * + Initialization and De-initialization.
+ * + LUT configuration.
+ * + Force flush and/or invalidate of cache.
+ * + Modify physical buffer adresses.
+ * + Modify cache and pre-fetch parameters.
+ * + Error management.
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ *** Initialization ***
+ ======================
+ [..]
+ (#) As prerequisite, fill in the HAL_GFXMMU_MspInit() :
+ (++) Enable GFXMMU clock interface with __HAL_RCC_GFXMMU_CLK_ENABLE().
+ (++) If interrupts are used, enable and configure GFXMMU global
+ interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
+ (#) Configure the number of blocks per line, default value, physical
+ buffer addresses, cache and pre-fetch parameters and interrupts
+ using the HAL_GFXMMU_Init() function.
+
+ *** LUT configuration ***
+ =========================
+ [..]
+ (#) Use HAL_GFXMMU_DisableLutLines() to deactivate all LUT lines (or a
+ range of lines).
+ (#) Use HAL_GFXMMU_ConfigLut() to copy LUT from flash to look up RAM.
+ (#) Use HAL_GFXMMU_ConfigLutLine() to configure one line of LUT.
+
+ *** Force flush and/or invalidate of cache ***
+ ==============================================
+ [..]
+ (#) Use HAL_GFXMMU_ConfigForceCache() to flush and/or invalidate cache.
+
+ *** Modify physical buffer adresses ***
+ =======================================
+ [..]
+ (#) Use HAL_GFXMMU_ModifyBuffers() to modify physical buffer addresses.
+
+ *** Modify cache and pre-fetch parameters ***
+ =============================================
+ [..]
+ (#) Use HAL_GFXMMU_ModifyCachePrefetch() to modify cache and pre-fetch
+ parameters.
+
+ *** Error management ***
+ ========================
+ [..]
+ (#) If interrupts are used, HAL_GFXMMU_IRQHandler() will be called when
+ an error occurs. This function will call HAL_GFXMMU_ErrorCallback().
+ Use HAL_GFXMMU_GetError() to get the error code.
+
+ *** De-initialization ***
+ =========================
+ [..]
+ (#) As prerequisite, fill in the HAL_GFXMMU_MspDeInit() :
+ (++) Disable GFXMMU clock interface with __HAL_RCC_GFXMMU_CLK_ENABLE().
+ (++) If interrupts has been used, disable GFXMMU global interrupt with
+ HAL_NVIC_DisableIRQ().
+ (#) De-initialize GFXMMU using the HAL_GFXMMU_DeInit() function.
+
+ *** Callback registration ***
+ =============================
+
+ [..]
+ The compilation define USE_HAL_GFXMMU_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use functions HAL_GFXMMU_RegisterCallback() to register a user callback.
+
+ [..]
+ Function HAL_GFXMMU_RegisterCallback() allows to register following callbacks:
+ (+) ErrorCallback : GFXMMU error.
+ (+) MspInitCallback : GFXMMU MspInit.
+ (+) MspDeInitCallback : GFXMMU MspDeInit.
+ [..]
+ This function takes as parameters the HAL peripheral handle, the callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function HAL_GFXMMU_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function.
+ HAL_GFXMMU_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the callback ID.
+ [..]
+ This function allows to reset following callbacks:
+ (+) ErrorCallback : GFXMMU error.
+ (+) MspInitCallback : GFXMMU MspInit.
+ (+) MspDeInitCallback : GFXMMU MspDeInit.
+
+ [..]
+ By default, after the HAL_GFXMMU_Init and if the state is HAL_GFXMMU_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions:
+ examples HAL_GFXMMU_ErrorCallback().
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the HAL_GFXMMU_Init
+ and HAL_GFXMMU_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_GFXMMU_Init and HAL_GFXMMU_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_GFXMMU_RegisterCallback before calling HAL_GFXMMU_DeInit
+ or HAL_GFXMMU_Init function.
+
+ [..]
+ When the compilation define USE_HAL_GFXMMU_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#ifdef HAL_GFXMMU_MODULE_ENABLED
+#if defined(GFXMMU)
+/** @defgroup GFXMMU GFXMMU
+ * @brief GFXMMU HAL driver module
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define GFXMMU_LUTXL_FVB_OFFSET 8U
+#define GFXMMU_LUTXL_LVB_OFFSET 16U
+#define GFXMMU_CR_ITS_MASK 0x1FU
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup GFXMMU_Exported_Functions GFXMMU Exported Functions
+ * @{
+ */
+
+/** @defgroup GFXMMU_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and de-initialization functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the GFXMMU.
+ (+) De-initialize the GFXMMU.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the GFXMMU according to the specified parameters in the
+ * GFXMMU_InitTypeDef structure and initialize the associated handle.
+ * @param hgfxmmu GFXMMU handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_Init(GFXMMU_HandleTypeDef *hgfxmmu)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check GFXMMU handle */
+ if(hgfxmmu == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check parameters */
+ assert_param(IS_GFXMMU_ALL_INSTANCE(hgfxmmu->Instance));
+ assert_param(IS_GFXMMU_BLOCKS_PER_LINE(hgfxmmu->Init.BlocksPerLine));
+ assert_param(IS_GFXMMU_BUFFER_ADDRESS(hgfxmmu->Init.Buffers.Buf0Address));
+ assert_param(IS_GFXMMU_BUFFER_ADDRESS(hgfxmmu->Init.Buffers.Buf1Address));
+ assert_param(IS_GFXMMU_BUFFER_ADDRESS(hgfxmmu->Init.Buffers.Buf2Address));
+ assert_param(IS_GFXMMU_BUFFER_ADDRESS(hgfxmmu->Init.Buffers.Buf3Address));
+ assert_param(IS_FUNCTIONAL_STATE(hgfxmmu->Init.CachePrefetch.Activation));
+ assert_param(IS_FUNCTIONAL_STATE(hgfxmmu->Init.Interrupts.Activation));
+
+#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1)
+ /* Reset callback pointers to the weak predefined callbacks */
+ hgfxmmu->ErrorCallback = HAL_GFXMMU_ErrorCallback;
+
+ /* Call GFXMMU MSP init function */
+ if(hgfxmmu->MspInitCallback == NULL)
+ {
+ hgfxmmu->MspInitCallback = HAL_GFXMMU_MspInit;
+ }
+ hgfxmmu->MspInitCallback(hgfxmmu);
+#else
+ /* Call GFXMMU MSP init function */
+ HAL_GFXMMU_MspInit(hgfxmmu);
+#endif
+
+ /* Configure blocks per line, cache and interrupts parameters on GFXMMU_CR register */
+ hgfxmmu->Instance->CR &= ~(GFXMMU_CR_B0OIE | GFXMMU_CR_B1OIE | GFXMMU_CR_B2OIE | GFXMMU_CR_B3OIE |
+ GFXMMU_CR_AMEIE | GFXMMU_CR_192BM | GFXMMU_CR_CE | GFXMMU_CR_CL |
+ GFXMMU_CR_CLB | GFXMMU_CR_FC | GFXMMU_CR_PD | GFXMMU_CR_OC |
+ GFXMMU_CR_OB);
+ hgfxmmu->Instance->CR |= (hgfxmmu->Init.BlocksPerLine);
+ if(hgfxmmu->Init.CachePrefetch.Activation == ENABLE)
+ {
+ assert_param(IS_GFXMMU_CACHE_LOCK(hgfxmmu->Init.CachePrefetch.CacheLock));
+ assert_param(IS_GFXMMU_PREFETCH(hgfxmmu->Init.CachePrefetch.Prefetch));
+ assert_param(IS_GFXMMU_OUTTER_BUFFERABILITY(hgfxmmu->Init.CachePrefetch.OutterBufferability));
+ assert_param(IS_GFXMMU_OUTTER_CACHABILITY(hgfxmmu->Init.CachePrefetch.OutterCachability));
+ hgfxmmu->Instance->CR |= (GFXMMU_CR_CE |
+ hgfxmmu->Init.CachePrefetch.CacheLock |
+ hgfxmmu->Init.CachePrefetch.Prefetch |
+ hgfxmmu->Init.CachePrefetch.OutterBufferability |
+ hgfxmmu->Init.CachePrefetch.OutterCachability);
+ if(hgfxmmu->Init.CachePrefetch.CacheLock == GFXMMU_CACHE_LOCK_ENABLE)
+ {
+ assert_param(IS_GFXMMU_CACHE_LOCK_BUFFER(hgfxmmu->Init.CachePrefetch.CacheLockBuffer));
+ assert_param(IS_GFXMMU_CACHE_FORCE(hgfxmmu->Init.CachePrefetch.CacheForce));
+ hgfxmmu->Instance->CR |= (hgfxmmu->Init.CachePrefetch.CacheLockBuffer |
+ hgfxmmu->Init.CachePrefetch.CacheForce);
+ }
+ }
+ if(hgfxmmu->Init.Interrupts.Activation == ENABLE)
+ {
+ assert_param(IS_GFXMMU_INTERRUPTS(hgfxmmu->Init.Interrupts.UsedInterrupts));
+ hgfxmmu->Instance->CR |= hgfxmmu->Init.Interrupts.UsedInterrupts;
+ }
+
+ /* Configure default value on GFXMMU_DVR register */
+ hgfxmmu->Instance->DVR = hgfxmmu->Init.DefaultValue;
+
+ /* Configure physical buffer adresses on GFXMMU_BxCR registers */
+ hgfxmmu->Instance->B0CR = hgfxmmu->Init.Buffers.Buf0Address;
+ hgfxmmu->Instance->B1CR = hgfxmmu->Init.Buffers.Buf1Address;
+ hgfxmmu->Instance->B2CR = hgfxmmu->Init.Buffers.Buf2Address;
+ hgfxmmu->Instance->B3CR = hgfxmmu->Init.Buffers.Buf3Address;
+
+ /* Force invalidate cache if cache is enabled */
+ if(hgfxmmu->Init.CachePrefetch.Activation == ENABLE)
+ {
+ hgfxmmu->Instance->CCR |= GFXMMU_CACHE_FORCE_INVALIDATE;
+ }
+
+ /* Reset GFXMMU error code */
+ hgfxmmu->ErrorCode = GFXMMU_ERROR_NONE;
+
+ /* Set GFXMMU to ready state */
+ hgfxmmu->State = HAL_GFXMMU_STATE_READY;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief De-initialize the GFXMMU.
+ * @param hgfxmmu GFXMMU handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_DeInit(GFXMMU_HandleTypeDef *hgfxmmu)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check GFXMMU handle */
+ if(hgfxmmu == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check parameters */
+ assert_param(IS_GFXMMU_ALL_INSTANCE(hgfxmmu->Instance));
+
+ /* Disable all interrupts on GFXMMU_CR register */
+ hgfxmmu->Instance->CR &= ~(GFXMMU_CR_B0OIE | GFXMMU_CR_B1OIE | GFXMMU_CR_B2OIE | GFXMMU_CR_B3OIE |
+ GFXMMU_CR_AMEIE);
+
+ /* Call GFXMMU MSP de-init function */
+#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1)
+ if(hgfxmmu->MspDeInitCallback == NULL)
+ {
+ hgfxmmu->MspDeInitCallback = HAL_GFXMMU_MspDeInit;
+ }
+ hgfxmmu->MspDeInitCallback(hgfxmmu);
+#else
+ HAL_GFXMMU_MspDeInit(hgfxmmu);
+#endif
+
+ /* Set GFXMMU to reset state */
+ hgfxmmu->State = HAL_GFXMMU_STATE_RESET;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Initialize the GFXMMU MSP.
+ * @param hgfxmmu GFXMMU handle.
+ * @retval None.
+ */
+__weak void HAL_GFXMMU_MspInit(GFXMMU_HandleTypeDef *hgfxmmu)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hgfxmmu);
+
+ /* NOTE : This function should not be modified, when the function is needed,
+ the HAL_GFXMMU_MspInit could be implemented in the user file.
+ */
+}
+
+/**
+ * @brief De-initialize the GFXMMU MSP.
+ * @param hgfxmmu GFXMMU handle.
+ * @retval None.
+ */
+__weak void HAL_GFXMMU_MspDeInit(GFXMMU_HandleTypeDef *hgfxmmu)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hgfxmmu);
+
+ /* NOTE : This function should not be modified, when the function is needed,
+ the HAL_GFXMMU_MspDeInit could be implemented in the user file.
+ */
+}
+
+#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a user GFXMMU callback
+ * to be used instead of the weak predefined callback.
+ * @param hgfxmmu GFXMMU handle.
+ * @param CallbackID ID of the callback to be registered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_GFXMMU_ERROR_CB_ID error callback ID.
+ * @arg @ref HAL_GFXMMU_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_GFXMMU_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @param pCallback pointer to the callback function.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_RegisterCallback(GFXMMU_HandleTypeDef *hgfxmmu,
+ HAL_GFXMMU_CallbackIDTypeDef CallbackID,
+ pGFXMMU_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* update the error code */
+ hgfxmmu->ErrorCode |= GFXMMU_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ if(HAL_GFXMMU_STATE_READY == hgfxmmu->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_GFXMMU_ERROR_CB_ID :
+ hgfxmmu->ErrorCallback = pCallback;
+ break;
+ case HAL_GFXMMU_MSPINIT_CB_ID :
+ hgfxmmu->MspInitCallback = pCallback;
+ break;
+ case HAL_GFXMMU_MSPDEINIT_CB_ID :
+ hgfxmmu->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update the error code */
+ hgfxmmu->ErrorCode |= GFXMMU_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_GFXMMU_STATE_RESET == hgfxmmu->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_GFXMMU_MSPINIT_CB_ID :
+ hgfxmmu->MspInitCallback = pCallback;
+ break;
+ case HAL_GFXMMU_MSPDEINIT_CB_ID :
+ hgfxmmu->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update the error code */
+ hgfxmmu->ErrorCode |= GFXMMU_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hgfxmmu->ErrorCode |= GFXMMU_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Unregister a user GFXMMU callback.
+ * GFXMMU callback is redirected to the weak predefined callback.
+ * @param hgfxmmu GFXMMU handle.
+ * @param CallbackID ID of the callback to be unregistered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_GFXMMU_ERROR_CB_ID error callback ID.
+ * @arg @ref HAL_GFXMMU_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_GFXMMU_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_UnRegisterCallback(GFXMMU_HandleTypeDef *hgfxmmu,
+ HAL_GFXMMU_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(HAL_GFXMMU_STATE_READY == hgfxmmu->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_GFXMMU_ERROR_CB_ID :
+ hgfxmmu->ErrorCallback = HAL_GFXMMU_ErrorCallback;
+ break;
+ case HAL_GFXMMU_MSPINIT_CB_ID :
+ hgfxmmu->MspInitCallback = HAL_GFXMMU_MspInit;
+ break;
+ case HAL_GFXMMU_MSPDEINIT_CB_ID :
+ hgfxmmu->MspDeInitCallback = HAL_GFXMMU_MspDeInit;
+ break;
+ default :
+ /* update the error code */
+ hgfxmmu->ErrorCode |= GFXMMU_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_GFXMMU_STATE_RESET == hgfxmmu->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_GFXMMU_MSPINIT_CB_ID :
+ hgfxmmu->MspInitCallback = HAL_GFXMMU_MspInit;
+ break;
+ case HAL_GFXMMU_MSPDEINIT_CB_ID :
+ hgfxmmu->MspDeInitCallback = HAL_GFXMMU_MspDeInit;
+ break;
+ default :
+ /* update the error code */
+ hgfxmmu->ErrorCode |= GFXMMU_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hgfxmmu->ErrorCode |= GFXMMU_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ return status;
+}
+#endif /* USE_HAL_GFXMMU_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup GFXMMU_Exported_Functions_Group2 Operations functions
+ * @brief GFXMMU operation functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Operation functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure LUT.
+ (+) Force flush and/or invalidate of cache.
+ (+) Modify physical buffer adresses.
+ (+) Modify cache and pre-fetch parameters.
+ (+) Manage error.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function allows to copy LUT from flash to look up RAM.
+ * @param hgfxmmu GFXMMU handle.
+ * @param FirstLine First line enabled on LUT.
+ * This parameter must be a number between Min_Data = 0 and Max_Data = 1023.
+ * @param LinesNumber Number of lines enabled on LUT.
+ * This parameter must be a number between Min_Data = 1 and Max_Data = 1024.
+ * @param Address Start address of LUT in flash.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_ConfigLut(GFXMMU_HandleTypeDef *hgfxmmu,
+ uint32_t FirstLine,
+ uint32_t LinesNumber,
+ uint32_t Address)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_GFXMMU_ALL_INSTANCE(hgfxmmu->Instance));
+ assert_param(IS_GFXMMU_LUT_LINE(FirstLine));
+ assert_param(IS_GFXMMU_LUT_LINES_NUMBER(LinesNumber));
+
+ /* Check GFXMMU state and coherent parameters */
+ if((hgfxmmu->State != HAL_GFXMMU_STATE_READY) || ((FirstLine + LinesNumber) > 1024U))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ uint32_t current_address, current_line, lutxl_address, lutxh_address;
+
+ /* Initialize local variables */
+ current_address = Address;
+ current_line = 0U;
+ lutxl_address = (uint32_t) &(hgfxmmu->Instance->LUT[2U * FirstLine]);
+ lutxh_address = (uint32_t) &(hgfxmmu->Instance->LUT[(2U * FirstLine) + 1U]);
+
+ /* Copy LUT from flash to look up RAM */
+ while(current_line < LinesNumber)
+ {
+ *((uint32_t *)lutxl_address) = *((uint32_t *)current_address);
+ current_address += 4U;
+ *((uint32_t *)lutxh_address) = *((uint32_t *)current_address);
+ current_address += 4U;
+ lutxl_address += 8U;
+ lutxh_address += 8U;
+ current_line++;
+ }
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to disable a range of LUT lines.
+ * @param hgfxmmu GFXMMU handle.
+ * @param FirstLine First line to disable on LUT.
+ * This parameter must be a number between Min_Data = 0 and Max_Data = 1023.
+ * @param LinesNumber Number of lines to disable on LUT.
+ * This parameter must be a number between Min_Data = 1 and Max_Data = 1024.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_DisableLutLines(GFXMMU_HandleTypeDef *hgfxmmu,
+ uint32_t FirstLine,
+ uint32_t LinesNumber)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_GFXMMU_ALL_INSTANCE(hgfxmmu->Instance));
+ assert_param(IS_GFXMMU_LUT_LINE(FirstLine));
+ assert_param(IS_GFXMMU_LUT_LINES_NUMBER(LinesNumber));
+
+ /* Check GFXMMU state and coherent parameters */
+ if((hgfxmmu->State != HAL_GFXMMU_STATE_READY) || ((FirstLine + LinesNumber) > 1024U))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ uint32_t current_line, lutxl_address, lutxh_address;
+
+ /* Initialize local variables */
+ current_line = 0U;
+ lutxl_address = (uint32_t) &(hgfxmmu->Instance->LUT[2U * FirstLine]);
+ lutxh_address = (uint32_t) &(hgfxmmu->Instance->LUT[(2U * FirstLine) + 1U]);
+
+ /* Disable LUT lines */
+ while(current_line < LinesNumber)
+ {
+ *((uint32_t *)lutxl_address) = 0U;
+ *((uint32_t *)lutxh_address) = 0U;
+ lutxl_address += 8U;
+ lutxh_address += 8U;
+ current_line++;
+ }
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to configure one line of LUT.
+ * @param hgfxmmu GFXMMU handle.
+ * @param lutLine LUT line parameters.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_ConfigLutLine(GFXMMU_HandleTypeDef *hgfxmmu, GFXMMU_LutLineTypeDef *lutLine)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_GFXMMU_ALL_INSTANCE(hgfxmmu->Instance));
+ assert_param(IS_GFXMMU_LUT_LINE(lutLine->LineNumber));
+ assert_param(IS_GFXMMU_LUT_LINE_STATUS(lutLine->LineStatus));
+ assert_param(IS_GFXMMU_LUT_BLOCK(lutLine->FirstVisibleBlock));
+ assert_param(IS_GFXMMU_LUT_BLOCK(lutLine->LastVisibleBlock));
+ assert_param(IS_GFXMMU_LUT_LINE_OFFSET(lutLine->LineOffset));
+
+ /* Check GFXMMU state */
+ if(hgfxmmu->State != HAL_GFXMMU_STATE_READY)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ uint32_t lutxl_address, lutxh_address;
+
+ /* Initialize local variables */
+ lutxl_address = (uint32_t) &(hgfxmmu->Instance->LUT[2U * lutLine->LineNumber]);
+ lutxh_address = (uint32_t) &(hgfxmmu->Instance->LUT[(2U * lutLine->LineNumber) + 1U]);
+
+ /* Configure LUT line */
+ if(lutLine->LineStatus == GFXMMU_LUT_LINE_ENABLE)
+ {
+ /* Enable and configure LUT line */
+ *((uint32_t *)lutxl_address) = (lutLine->LineStatus |
+ (lutLine->FirstVisibleBlock << GFXMMU_LUTXL_FVB_OFFSET) |
+ (lutLine->LastVisibleBlock << GFXMMU_LUTXL_LVB_OFFSET));
+ *((uint32_t *)lutxh_address) = (uint32_t) lutLine->LineOffset;
+ }
+ else
+ {
+ /* Disable LUT line */
+ *((uint32_t *)lutxl_address) = 0U;
+ *((uint32_t *)lutxh_address) = 0U;
+ }
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to force flush and/or invalidate of cache.
+ * @param hgfxmmu GFXMMU handle.
+ * @param ForceParam Force cache parameter.
+ * This parameter can be a values combination of @ref GFXMMU_CacheForceParam.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_ConfigForceCache(GFXMMU_HandleTypeDef *hgfxmmu, uint32_t ForceParam)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_GFXMMU_ALL_INSTANCE(hgfxmmu->Instance));
+ assert_param(IS_GFXMMU_CACHE_FORCE_ACTION(ForceParam));
+
+ /* Check GFXMMU state and cache status */
+ if(((hgfxmmu->Instance->CR & GFXMMU_CR_CE) != GFXMMU_CR_CE) || (hgfxmmu->State != HAL_GFXMMU_STATE_READY))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Force flush and/or invalidate cache on GFXMMU_CCR register */
+ hgfxmmu->Instance->CCR |= ForceParam;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to modify physical buffer addresses.
+ * @param hgfxmmu GFXMMU handle.
+ * @param Buffers Buffers parameters.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_ModifyBuffers(GFXMMU_HandleTypeDef *hgfxmmu, GFXMMU_BuffersTypeDef *Buffers)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_GFXMMU_ALL_INSTANCE(hgfxmmu->Instance));
+ assert_param(IS_GFXMMU_BUFFER_ADDRESS(Buffers->Buf0Address));
+ assert_param(IS_GFXMMU_BUFFER_ADDRESS(Buffers->Buf1Address));
+ assert_param(IS_GFXMMU_BUFFER_ADDRESS(Buffers->Buf2Address));
+ assert_param(IS_GFXMMU_BUFFER_ADDRESS(Buffers->Buf3Address));
+
+ /* Check GFXMMU state */
+ if(hgfxmmu->State != HAL_GFXMMU_STATE_READY)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Modify physical buffer adresses on GFXMMU_BxCR registers */
+ hgfxmmu->Instance->B0CR = Buffers->Buf0Address;
+ hgfxmmu->Instance->B1CR = Buffers->Buf1Address;
+ hgfxmmu->Instance->B2CR = Buffers->Buf2Address;
+ hgfxmmu->Instance->B3CR = Buffers->Buf3Address;
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function allows to modify cache and pre-fetch parameters.
+ * @param hgfxmmu GFXMMU handle.
+ * @param CachePrefetch Cache and pre-fetch parameters.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_GFXMMU_ModifyCachePrefetch(GFXMMU_HandleTypeDef *hgfxmmu,
+ GFXMMU_CachePrefetchTypeDef *CachePrefetch)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ assert_param(IS_FUNCTIONAL_STATE(CachePrefetch->Activation));
+
+ /* Check parameters */
+ assert_param(IS_GFXMMU_ALL_INSTANCE(hgfxmmu->Instance));
+
+ /* Check GFXMMU state */
+ if(hgfxmmu->State != HAL_GFXMMU_STATE_READY)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Modify cache and pre-fetch parameters on GFXMMU_CR register */
+ hgfxmmu->Instance->CR &= ~(GFXMMU_CR_CE | GFXMMU_CR_CL | GFXMMU_CR_CLB | GFXMMU_CR_FC |
+ GFXMMU_CR_PD | GFXMMU_CR_OC | GFXMMU_CR_OB);
+ if(CachePrefetch->Activation == ENABLE)
+ {
+ assert_param(IS_GFXMMU_CACHE_LOCK(CachePrefetch->CacheLock));
+ assert_param(IS_GFXMMU_PREFETCH(CachePrefetch->Prefetch));
+ assert_param(IS_GFXMMU_OUTTER_BUFFERABILITY(CachePrefetch->OutterBufferability));
+ assert_param(IS_GFXMMU_OUTTER_CACHABILITY(CachePrefetch->OutterCachability));
+ hgfxmmu->Instance->CR |= (GFXMMU_CR_CE |
+ CachePrefetch->CacheLock |
+ CachePrefetch->Prefetch |
+ CachePrefetch->OutterBufferability |
+ CachePrefetch->OutterCachability);
+ if(CachePrefetch->CacheLock == GFXMMU_CACHE_LOCK_ENABLE)
+ {
+ assert_param(IS_GFXMMU_CACHE_LOCK_BUFFER(CachePrefetch->CacheLockBuffer));
+ assert_param(IS_GFXMMU_CACHE_FORCE(CachePrefetch->CacheForce));
+ hgfxmmu->Instance->CR |= (CachePrefetch->CacheLockBuffer |
+ CachePrefetch->CacheForce);
+ }
+ }
+ }
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function handles the GFXMMU interrupts.
+ * @param hgfxmmu GFXMMU handle.
+ * @retval None.
+ */
+void HAL_GFXMMU_IRQHandler(GFXMMU_HandleTypeDef *hgfxmmu)
+{
+ uint32_t flags, interrupts, error;
+
+ /* Read current flags and interrupts and determine which error occurs */
+ flags = hgfxmmu->Instance->SR;
+ interrupts = (hgfxmmu->Instance->CR & GFXMMU_CR_ITS_MASK);
+ error = (flags & interrupts);
+
+ if(error != 0U)
+ {
+ /* Clear flags on GFXMMU_FCR register */
+ hgfxmmu->Instance->FCR = error;
+
+ /* Update GFXMMU error code */
+ hgfxmmu->ErrorCode |= error;
+
+ /* Call GFXMMU error callback */
+#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1)
+ hgfxmmu->ErrorCallback(hgfxmmu);
+#else
+ HAL_GFXMMU_ErrorCallback(hgfxmmu);
+#endif
+ }
+}
+
+/**
+ * @brief Error callback.
+ * @param hgfxmmu GFXMMU handle.
+ * @retval None.
+ */
+__weak void HAL_GFXMMU_ErrorCallback(GFXMMU_HandleTypeDef *hgfxmmu)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hgfxmmu);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_GFXMMU_ErrorCallback could be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup GFXMMU_Exported_Functions_Group3 State functions
+ * @brief GFXMMU state functions
+ *
+@verbatim
+ ==============================================================================
+ ##### State functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Get GFXMMU handle state.
+ (+) Get GFXMMU error code.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function allows to get the current GFXMMU handle state.
+ * @param hgfxmmu GFXMMU handle.
+ * @retval GFXMMU state.
+ */
+HAL_GFXMMU_StateTypeDef HAL_GFXMMU_GetState(GFXMMU_HandleTypeDef *hgfxmmu)
+{
+ /* Return GFXMMU handle state */
+ return hgfxmmu->State;
+}
+
+/**
+ * @brief This function allows to get the current GFXMMU error code.
+ * @param hgfxmmu GFXMMU handle.
+ * @retval GFXMMU error code.
+ */
+uint32_t HAL_GFXMMU_GetError(GFXMMU_HandleTypeDef *hgfxmmu)
+{
+ uint32_t error_code;
+
+ /* Enter in critical section */
+ __disable_irq();
+
+ /* Store and reset GFXMMU error code */
+ error_code = hgfxmmu->ErrorCode;
+ hgfxmmu->ErrorCode = GFXMMU_ERROR_NONE;
+
+ /* Exit from critical section */
+ __enable_irq();
+
+ /* Return GFXMMU error code */
+ return error_code;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* End of exported functions -------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* End of private functions --------------------------------------------------*/
+
+/**
+ * @}
+ */
+#endif /* GFXMMU */
+#endif /* HAL_GFXMMU_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_gpio.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_gpio.c
new file mode 100644
index 0000000000..13dcc40d20
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_gpio.c
@@ -0,0 +1,560 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ @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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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
+ * @{
+ */
+#define GPIO_MODE (0x00000003U)
+#define ANALOG_MODE (0x00000008U)
+#define EXTI_MODE (0x10000000U)
+#define GPIO_MODE_IT (0x00010000U)
+#define GPIO_MODE_EVT (0x00020000U)
+#define RISING_EDGE (0x00100000U)
+#define FALLING_EDGE (0x00200000U)
+#define GPIO_OUTPUT_TYPE (0x00000010U)
+
+#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, 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));
+ assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
+
+ /* Configure the port pins */
+ while (((GPIO_Init->Pin) >> position) != 0x00U)
+ {
+ /* Get current io position */
+ iocurrent = (GPIO_Init->Pin) & (1UL << position);
+
+ if (iocurrent != 0x00U)
+ {
+ /*--------------------- GPIO Mode Configuration ------------------------*/
+ /* In case of Output or Alternate function mode selection */
+ if ((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
+ (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
+ {
+ /* Check the Speed parameter */
+ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
+ /* Configure the IO Speed */
+ temp = GPIOx->OSPEEDR;
+ temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 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 & GPIO_OUTPUT_TYPE) >> 4U) << position);
+ GPIOx->OTYPER = temp;
+ }
+
+ /* 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_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
+ {
+ /* Check the Alternate function parameters */
+ assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
+ assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
+
+ /* Configure Alternate function mapped with the current IO */
+ temp = GPIOx->AFR[position >> 3U];
+ temp &= ~(0xFU << ((position & 0x07U) * 4U));
+ temp |= ((GPIO_Init->Alternate) << ((position & 0x07U) * 4U));
+ GPIOx->AFR[position >> 3U] = temp;
+ }
+
+ /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
+ temp = GPIOx->MODER;
+ temp &= ~(GPIO_MODER_MODE0 << (position * 2U));
+ temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2U));
+ GPIOx->MODER = temp;
+
+ /*--------------------- EXTI Mode Configuration ------------------------*/
+ /* Configure the External Interrupt or event for the current IO */
+ if ((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
+ {
+ /* 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 EXTI line configuration */
+ temp = EXTI_CurrentCPU->IMR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
+ {
+ temp |= iocurrent;
+ }
+ EXTI_CurrentCPU->IMR1 = temp;
+
+ temp = EXTI_CurrentCPU->EMR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
+ {
+ temp |= iocurrent;
+ }
+ EXTI_CurrentCPU->EMR1 = temp;
+
+ /* Clear Rising Falling edge configuration */
+ temp = EXTI->RTSR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->RTSR1 = temp;
+
+ temp = EXTI->FTSR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->FTSR1 = 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->RTSR1 &= ~(iocurrent);
+ EXTI->FTSR1 &= ~(iocurrent);
+
+ tmp = 0x0FUL << (4U * (position & 0x03U));
+ SYSCFG->EXTICR[position >> 2U] &= ~tmp;
+ }
+
+ /*------------------------- GPIO Mode Configuration --------------------*/
+ /* Configure IO in Analog Mode */
+ GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2U));
+
+ /* Configure the default Alternate Function in current IO */
+ GPIOx->AFR[position >> 3U] &= ~(0xFU << ((position & 0x07U) * 4U)) ;
+
+ /* Deactivate the Pull-up and Pull-down resistor for the current IO */
+ GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2U));
+
+ /* Configure the default value IO Output Type */
+ GPIOx->OTYPER &= ~(GPIO_OTYPER_OT0 << position) ;
+
+ /* Configure the default value for IO Speed */
+ GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2U));
+ }
+
+ position++;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @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(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)
+{
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ if ((GPIOx->ODR & GPIO_Pin) == GPIO_Pin)
+ {
+ GPIOx->BSRR = (uint32_t)GPIO_Pin << GPIO_NUMBER;
+ }
+ else
+ {
+ GPIOx->BSRR = 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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_hash.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hash.c
new file mode 100644
index 0000000000..22b4362526
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hash.c
@@ -0,0 +1,3445 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_hash.c
+ * @author MCD Application Team
+ * @brief HASH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the HASH peripheral:
+ * + Initialization and de-initialization methods
+ * + HASH or HMAC processing in polling mode
+ * + HASH or HMAC processing in interrupt mode
+ * + HASH or HMAC processing in DMA mode
+ * + Peripheral State methods
+ * + HASH or HMAC processing suspension/resumption
+ *
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The HASH HAL driver can be used as follows:
+
+ (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit():
+ (##) Enable the HASH interface clock using __HASH_CLK_ENABLE()
+ (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT())
+ (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority()
+ (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ()
+ (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API
+ (##) When resorting to DMA-based APIs (e.g. HAL_HASH_xxx_Start_DMA())
+ (+++) Enable the DMAx interface clock using
+ __DMAx_CLK_ENABLE()
+ (+++) Configure and enable one DMA stream to manage data transfer from
+ memory to peripheral (input stream). Managing data transfer from
+ peripheral to memory can be performed only using CPU.
+ (+++) Associate the initialized DMA handle to the HASH DMA handle
+ using __HAL_LINKDMA()
+ (+++) Configure the priority and enable the NVIC for the transfer complete
+ interrupt on the DMA Stream: use
+ HAL_NVIC_SetPriority() and
+ HAL_NVIC_EnableIRQ()
+
+ (#)Initialize the HASH HAL using HAL_HASH_Init(). This function:
+ (##) resorts to HAL_HASH_MspInit() for low-level initialization,
+ (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit.
+
+ (#)Three processing schemes are available:
+ (##) Polling mode: processing APIs are blocking functions
+ i.e. they process the data and wait till the digest computation is finished,
+ e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC
+ (##) Interrupt mode: processing APIs are not blocking functions
+ i.e. they process the data under interrupt,
+ e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC
+ (##) DMA mode: processing APIs are not blocking functions and the CPU is
+ not used for data transfer i.e. the data transfer is ensured by DMA,
+ e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA()
+ for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish()
+ is then required to retrieve the digest.
+
+ (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is
+ initialized and processes the buffer fed in input. When the input data have all been
+ fed to the Peripheral, the digest computation can start.
+
+ (#)Multi-buffer processing is possible in polling, interrupt and DMA modes.
+ (##) In polling mode, only multi-buffer HASH processing is possible.
+ API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one.
+ User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as
+ well the computed digest.
+
+ (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer,
+ except for the last one.
+ User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as
+ well the computed digest.
+
+ (##) In DMA mode, multi-buffer HASH and HMAC processing are possible.
+ (+++) HASH processing: once initialization is done, MDMAT bit must be set thru __HAL_HASH_SET_MDMAT() macro.
+ From that point, each buffer can be fed to the Peripheral thru HAL_HASH_xxx_Start_DMA() API.
+ Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT()
+ macro then wrap-up the HASH processing in feeding the last input buffer thru the
+ same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to
+ API HAL_HASH_xxx_Finish().
+ (+++) HMAC processing (requires to resort to extended functions):
+ after initialization, the key and the first input buffer are entered
+ in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
+ starts step 2.
+ The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this
+ point, the HMAC processing is still carrying out step 2.
+ Then, step 2 for the last input buffer and step 3 are carried out by a single call
+ to HAL_HMACEx_xxx_Step2_3_DMA().
+
+ The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish().
+
+
+ (#)Context swapping.
+ (##) Two APIs are available to suspend HASH or HMAC processing:
+ (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode),
+ (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA.
+
+ (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows
+ to save in memory the Peripheral context. This context can be restored afterwards
+ to resume the HASH processing thanks to HAL_HASH_ContextRestoring().
+
+ (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension
+ time, processing can be restarted with the same API call (same API, same handle,
+ same parameters) as done before the suspension. Relevant parameters to restart at
+ the proper location are internally saved in the HASH handle.
+
+ (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
+
+ *** Remarks on message length ***
+ ===================================
+ [..]
+ (#) HAL in interruption mode (interruptions driven)
+
+ (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes.
+ This is why, for driver implementation simplicity’s sake, user is requested to enter a message the
+ length of which is a multiple of 4 bytes.
+
+ (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR
+ to specify which bits to discard at the end of the complete message to process only the message bits
+ and not extra bits.
+
+ (##) If user needs to perform a hash computation of a large input buffer that is spread around various places
+ in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it
+ becomes necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral.
+ It is advised to the user to
+ (+++) achieve the first formatting operation by software then enter the data
+ (+++) while the Peripheral is processing the first input set, carry out the second formatting operation by software, to be ready when DINIS occurs.
+ (+++) repeat step 2 until the whole message is processed.
+
+ [..]
+ (#) HAL in DMA mode
+
+ (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis.
+ The same field described above in HASH_STR is used to specify which bits to discard at the end of the DMA transfer
+ to process only the message bits and not extra bits. Due to hardware implementation, this is possible only at the
+ end of the complete message. When several DMA transfers are needed to enter the message, this is not applicable at
+ the end of the intermediary transfers.
+
+ (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive chunks of data
+ by software while the DMA transfer and processing is on-going for the first parts of the message. Due to the 32-bit alignment
+ required for the DMA transfer, it is underlined that the software formatting operation is more complex than in the IT mode.
+
+ *** Callback registration ***
+ ===================================
+ [..]
+ (#) The compilation define USE_HAL_HASH_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use function @ref HAL_HASH_RegisterCallback() to register a user callback.
+
+ (#) Function @ref HAL_HASH_RegisterCallback() allows to register following callbacks:
+ (+) InCpltCallback : callback for input completion.
+ (+) DgstCpltCallback : callback for digest computation completion.
+ (+) ErrorCallback : callback for error.
+ (+) MspInitCallback : HASH MspInit.
+ (+) MspDeInitCallback : HASH MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ (#) Use function @ref HAL_HASH_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function.
+ @ref HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) InCpltCallback : callback for input completion.
+ (+) DgstCpltCallback : callback for digest computation completion.
+ (+) ErrorCallback : callback for error.
+ (+) MspInitCallback : HASH MspInit.
+ (+) MspDeInitCallback : HASH MspDeInit.
+
+ (#) By default, after the @ref HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions:
+ examples @ref HAL_HASH_InCpltCallback(), @ref HAL_HASH_DgstCpltCallback()
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_HASH_Init
+ and @ref HAL_HASH_DeInit only when these callbacks are null (not registered beforehand)
+ If not, MspInit or MspDeInit are not null, the @ref HAL_HASH_Init and @ref HAL_HASH_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 @ref HAL_HASH_RegisterCallback before calling @ref HAL_HASH_DeInit
+ or @ref HAL_HASH_Init function.
+
+ When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#if defined (HASH)
+
+/** @defgroup HASH HASH
+ * @brief HASH HAL module driver.
+ * @{
+ */
+
+#ifdef HAL_HASH_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup HASH_Private_Constants HASH Private Constants
+ * @{
+ */
+
+/** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status
+ * @{
+ */
+#define HASH_DIGEST_CALCULATION_NOT_STARTED ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */
+#define HASH_DIGEST_CALCULATION_STARTED ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register */
+/**
+ * @}
+ */
+
+/** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers
+ * @{
+ */
+#define HASH_NUMBER_OF_CSR_REGISTERS 54U /*!< Number of Context Swap Registers */
+/**
+ * @}
+ */
+
+/** @defgroup HASH_TimeOut_Value HASH TimeOut Value
+ * @{
+ */
+#define HASH_TIMEOUTVALUE 1000U /*!< Time-out value */
+/**
+ * @}
+ */
+
+/** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit
+ * @{
+ */
+#define HASH_DMA_SUSPENSION_WORDS_LIMIT 20U /*!< Number of words below which DMA suspension is aborted */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup HASH_Private_Functions HASH Private Functions
+ * @{
+ */
+static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma);
+static void HASH_DMAError(DMA_HandleTypeDef *hdma);
+static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size);
+static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, uint32_t Timeout);
+static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size);
+static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash);
+static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash);
+static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout);
+/**
+ * @}
+ */
+
+/** @defgroup HASH_Exported_Functions HASH Exported Functions
+ * @{
+ */
+
+/** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization, configuration and call-back functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the HASH according to the specified parameters
+ in the HASH_InitTypeDef and create the associated handle
+ (+) DeInitialize the HASH peripheral
+ (+) Initialize the HASH MCU Specific Package (MSP)
+ (+) DeInitialize the HASH MSP
+
+ [..] This section provides as well call back functions definitions for user
+ code to manage:
+ (+) Input data transfer to Peripheral completion
+ (+) Calculated digest retrieval completion
+ (+) Error management
+
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the HASH according to the specified parameters in the
+ HASH_HandleTypeDef and create the associated handle.
+ * @note Only MDMAT and DATATYPE bits of HASH Peripheral are set by HAL_HASH_Init(),
+ * other configuration bits are set by HASH or HMAC processing APIs.
+ * @note MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for
+ * multi-buffer HASH processing, user needs to resort to
+ * __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the
+ * relevant APIs manage themselves the MDMAT bit.
+ * @param hhash HASH handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash)
+{
+ /* Check the hash handle allocation */
+ if(hhash == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_HASH_DATATYPE(hhash->Init.DataType));
+
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ if (hhash->State == HAL_HASH_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hhash->Lock = HAL_UNLOCKED;
+
+ /* Reset Callback pointers in HAL_HASH_STATE_RESET only */
+ hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */
+ hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation completion callback */
+ hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */
+ if(hhash->MspInitCallback == NULL)
+ {
+ hhash->MspInitCallback = HAL_HASH_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hhash->MspInitCallback(hhash);
+ }
+#else
+ if(hhash->State == HAL_HASH_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hhash->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware */
+ HAL_HASH_MspInit(hhash);
+ }
+#endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */
+ hhash->HashInCount = 0;
+ hhash->HashBuffSize = 0;
+ hhash->HashITCounter = 0;
+ hhash->NbWordsAlreadyPushed = 0;
+ /* Reset digest calculation bridle (MDMAT bit control) */
+ hhash->DigestCalculationDisable = RESET;
+ /* Set phase to READY */
+ hhash->Phase = HAL_HASH_PHASE_READY;
+ /* Reset suspension request flag */
+ hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
+
+ /* Set the data type bit */
+ MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType);
+ /* Reset MDMAT bit */
+__HAL_HASH_RESET_MDMAT();
+ /* Reset HASH handle status */
+ hhash->Status = HAL_OK;
+
+ /* Set the HASH state to Ready */
+ hhash->State = HAL_HASH_STATE_READY;
+
+ /* Initialise the error code */
+ hhash->ErrorCode = HAL_HASH_ERROR_NONE;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the HASH peripheral.
+ * @param hhash HASH handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash)
+{
+ /* Check the HASH handle allocation */
+ if(hhash == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Set the default HASH phase */
+ hhash->Phase = HAL_HASH_PHASE_READY;
+
+ /* Reset HashInCount, HashITCounter and HashBuffSize */
+ hhash->HashInCount = 0;
+ hhash->HashBuffSize = 0;
+ hhash->HashITCounter = 0;
+ /* Reset digest calculation bridle (MDMAT bit control) */
+ hhash->DigestCalculationDisable = RESET;
+
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ if(hhash->MspDeInitCallback == NULL)
+ {
+ hhash->MspDeInitCallback = HAL_HASH_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hhash->MspDeInitCallback(hhash);
+#else
+ /* DeInit the low level hardware: CLOCK, NVIC */
+ HAL_HASH_MspDeInit(hhash);
+#endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
+
+
+ /* Reset HASH handle status */
+ hhash->Status = HAL_OK;
+
+ /* Set the HASH state to Ready */
+ hhash->State = HAL_HASH_STATE_RESET;
+
+ /* Initialise the error code */
+ hhash->ErrorCode = HAL_HASH_ERROR_NONE;
+
+ /* Reset multi buffers accumulation flag */
+ hhash->Accumulation = 0U;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the HASH MSP.
+ * @param hhash HASH handle.
+ * @retval None
+ */
+__weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhash);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_HASH_MspInit() can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief DeInitialize the HASH MSP.
+ * @param hhash HASH handle.
+ * @retval None
+ */
+__weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhash);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_HASH_MspDeInit() can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Input data transfer complete call back.
+ * @note HAL_HASH_InCpltCallback() is called when the complete input message
+ * has been fed to the Peripheral. This API is invoked only when input data are
+ * entered under interruption or thru DMA.
+ * @note In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set),
+ * HAL_HASH_InCpltCallback() is called at the end of each buffer feeding
+ * to the Peripheral.
+ * @param hhash HASH handle.
+ * @retval None
+ */
+__weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhash);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_HASH_InCpltCallback() can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Digest computation complete call back.
+ * @note HAL_HASH_DgstCpltCallback() is used under interruption, is not
+ * relevant with DMA.
+ * @param hhash HASH handle.
+ * @retval None
+ */
+__weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhash);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_HASH_DgstCpltCallback() can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Error callback.
+ * @note Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...)
+ * to retrieve the error type.
+ * @param hhash HASH handle.
+ * @retval None
+ */
+__weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhash);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_HASH_ErrorCallback() can be implemented in the user file.
+ */
+}
+
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User HASH Callback
+ * To be used instead of the weak (surcharged) predefined callback
+ * @param hhash HASH handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
+ * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
+ * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
+ * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
+ * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID, pHASH_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hhash);
+
+ if(HAL_HASH_STATE_READY == hhash->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HASH_INPUTCPLT_CB_ID :
+ hhash->InCpltCallback = pCallback;
+ break;
+
+ case HAL_HASH_DGSTCPLT_CB_ID :
+ hhash->DgstCpltCallback = pCallback;
+ break;
+
+ case HAL_HASH_ERROR_CB_ID :
+ hhash->ErrorCallback = pCallback;
+ break;
+
+ case HAL_HASH_MSPINIT_CB_ID :
+ hhash->MspInitCallback = pCallback;
+ break;
+
+ case HAL_HASH_MSPDEINIT_CB_ID :
+ hhash->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_HASH_STATE_RESET == hhash->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HASH_MSPINIT_CB_ID :
+ hhash->MspInitCallback = pCallback;
+ break;
+
+ case HAL_HASH_MSPDEINIT_CB_ID :
+ hhash->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhash);
+ return status;
+}
+
+/**
+ * @brief Unregister a HASH Callback
+ * HASH Callback is redirected to the weak (surcharged) predefined callback
+ * @param hhash HASH handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
+ * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
+ * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
+ * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
+ * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID)
+{
+HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hhash);
+
+ if(HAL_HASH_STATE_READY == hhash->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HASH_INPUTCPLT_CB_ID :
+ hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */
+ break;
+
+ case HAL_HASH_DGSTCPLT_CB_ID :
+ hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation completion callback */
+ break;
+
+ case HAL_HASH_ERROR_CB_ID :
+ hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */
+ break;
+
+ case HAL_HASH_MSPINIT_CB_ID :
+ hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */
+ break;
+
+ case HAL_HASH_MSPDEINIT_CB_ID :
+ hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_HASH_STATE_RESET == hhash->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HASH_MSPINIT_CB_ID :
+ hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */
+ break;
+
+ case HAL_HASH_MSPDEINIT_CB_ID :
+ hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhash);
+ return status;
+}
+#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode
+ * @brief HASH processing functions using polling mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### Polling mode HASH processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in polling mode
+ the hash value using one of the following algorithms:
+ (+) MD5
+ (++) HAL_HASH_MD5_Start()
+ (++) HAL_HASH_MD5_Accmlt()
+ (++) HAL_HASH_MD5_Accmlt_End()
+ (+) SHA1
+ (++) HAL_HASH_SHA1_Start()
+ (++) HAL_HASH_SHA1_Accmlt()
+ (++) HAL_HASH_SHA1_Accmlt_End()
+
+ [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
+
+ [..] In case of multi-buffer HASH processing (a single digest is computed while
+ several buffers are fed to the Peripheral), the user can resort to successive calls
+ to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call
+ to HAL_HASH_xxx_Accumulate_End().
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
+ * @param Timeout Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief If not already done, initialize the HASH peripheral in MD5 mode then
+ * processes pInBuffer.
+ * @note Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed
+ * several input buffers back-to-back to the Peripheral that will yield a single
+ * HASH signature once all buffers have been entered. Wrap-up of input
+ * buffers feeding and retrieval of digest is done by a call to
+ * HAL_HASH_MD5_Accmlt_End().
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End()
+ * to read it, feeding at the same time the last input buffer to the Peripheral.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able
+ * to manage the ending buffer with a length in bytes not a multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
+ * @param Timeout Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
+ * @param Timeout Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @brief If not already done, initialize the HASH peripheral in SHA1 mode then
+ * processes pInBuffer.
+ * @note Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed
+ * several input buffers back-to-back to the Peripheral that will yield a single
+ * HASH signature once all buffers have been entered. Wrap-up of input
+ * buffers feeding and retrieval of digest is done by a call to
+ * HAL_HASH_SHA1_Accmlt_End().
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End()
+ * to read it, feeding at the same time the last input buffer to the Peripheral.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able
+ * to manage the ending buffer with a length in bytes not a multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
+ * @param Timeout Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode
+ * @brief HASH processing functions using interrupt mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### Interruption mode HASH processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in interrupt mode
+ the hash value using one of the following algorithms:
+ (+) MD5
+ (++) HAL_HASH_MD5_Start_IT()
+ (++) HAL_HASH_MD5_Accmlt_IT()
+ (++) HAL_HASH_MD5_Accmlt_End_IT()
+ (+) SHA1
+ (++) HAL_HASH_SHA1_Start_IT()
+ (++) HAL_HASH_SHA1_Accmlt_IT()
+ (++) HAL_HASH_SHA1_Accmlt_End_IT()
+
+ [..] API HAL_HASH_IRQHandler() manages each HASH interruption.
+
+ [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in
+ HMAC processing mode.
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
+ * read the computed digest in interruption mode.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief If not already done, initialize the HASH peripheral in MD5 mode then
+ * processes pInBuffer in interruption mode.
+ * @note Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed
+ * several input buffers back-to-back to the Peripheral that will yield a single
+ * HASH signature once all buffers have been entered. Wrap-up of input
+ * buffers feeding and retrieval of digest is done by a call to
+ * HAL_HASH_MD5_Accmlt_End_IT().
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able
+ * to manage the ending buffer with a length in bytes not a multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Accumulate_IT(hhash, pInBuffer, Size,HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
+ * read the computed digest in interruption mode.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA1);
+}
+
+
+/**
+ * @brief If not already done, initialize the HASH peripheral in SHA1 mode then
+ * processes pInBuffer in interruption mode.
+ * @note Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed
+ * several input buffers back-to-back to the Peripheral that will yield a single
+ * HASH signature once all buffers have been entered. Wrap-up of input
+ * buffers feeding and retrieval of digest is done by a call to
+ * HAL_HASH_SHA1_Accmlt_End_IT().
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able
+ * to manage the ending buffer with a length in bytes not a multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Accumulate_IT(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @brief Handle HASH interrupt request.
+ * @param hhash HASH handle.
+ * @note HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well.
+ * @note In case of error reported during the HASH interruption processing,
+ * HAL_HASH_ErrorCallback() API is called so that user code can
+ * manage the error. The error type is available in hhash->Status field.
+ * @retval None
+ */
+void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash)
+{
+ hhash->Status = HASH_IT(hhash);
+ if (hhash->Status != HAL_OK)
+ {
+ hhash->ErrorCode |= HAL_HASH_ERROR_IT;
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ hhash->ErrorCallback(hhash);
+#else
+ HAL_HASH_ErrorCallback(hhash);
+#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
+ /* After error handling by code user, reset HASH handle HAL status */
+ hhash->Status = HAL_OK;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode
+ * @brief HASH processing functions using DMA mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### DMA mode HASH processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in DMA mode
+ the hash value using one of the following algorithms:
+ (+) MD5
+ (++) HAL_HASH_MD5_Start_DMA()
+ (++) HAL_HASH_MD5_Finish()
+ (+) SHA1
+ (++) HAL_HASH_SHA1_Start_DMA()
+ (++) HAL_HASH_SHA1_Finish()
+
+ [..] When resorting to DMA mode to enter the data in the Peripheral, user must resort
+ to HAL_HASH_xxx_Start_DMA() then read the resulting digest with
+ HAL_HASH_xxx_Finish().
+ [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before
+ the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be
+ reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally
+ retrieved thanks to HAL_HASH_xxx_Finish().
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer
+ * to feed the input buffer to the Peripheral.
+ * @note Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must
+ * be called to retrieve the computed digest.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief Return the computed digest in MD5 mode.
+ * @note The API waits for DCIS to be set then reads the computed digest.
+ * @note HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in
+ * HMAC MD5 mode.
+ * @param hhash HASH handle.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Finish(hhash, pOutBuffer, Timeout);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer
+ * to feed the input buffer to the Peripheral.
+ * @note Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must
+ * be called to retrieve the computed digest.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
+}
+
+
+/**
+ * @brief Return the computed digest in SHA1 mode.
+ * @note The API waits for DCIS to be set then reads the computed digest.
+ * @note HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in
+ * HMAC SHA1 mode.
+ * @param hhash HASH handle.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Finish(hhash, pOutBuffer, Timeout);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode
+ * @brief HMAC processing functions using polling mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### Polling mode HMAC processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in polling mode
+ the HMAC value using one of the following algorithms:
+ (+) MD5
+ (++) HAL_HMAC_MD5_Start()
+ (+) SHA1
+ (++) HAL_HMAC_SHA1_Start()
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @}
+ */
+
+
+/** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
+ * @brief HMAC processing functions using interrupt mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### Interrupt mode HMAC processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in interrupt mode
+ the HMAC value using one of the following algorithms:
+ (+) MD5
+ (++) HAL_HMAC_MD5_Start_IT()
+ (+) SHA1
+ (++) HAL_HMAC_SHA1_Start_IT()
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
+ * read the computed digest in interrupt mode.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
+ * read the computed digest in interrupt mode.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
+ * @brief HMAC processing functions using DMA modes.
+ *
+@verbatim
+ ===============================================================================
+ ##### DMA mode HMAC processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in DMA mode
+ the HMAC value using one of the following algorithms:
+ (+) MD5
+ (++) HAL_HMAC_MD5_Start_DMA()
+ (+) SHA1
+ (++) HAL_HMAC_SHA1_Start_DMA()
+
+ [..] When resorting to DMA mode to enter the data in the Peripheral for HMAC processing,
+ user must resort to HAL_HMAC_xxx_Start_DMA() then read the resulting digest
+ with HAL_HASH_xxx_Finish().
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
+ * DMA transfers to feed the key and the input buffer to the Peripheral.
+ * @note Once the DMA transfers are finished (indicated by hhash->State set back
+ * to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
+ * the computed digest.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note If MDMAT bit is set before calling this function (multi-buffer
+ * HASH processing case), the input buffer size (in bytes) must be
+ * a multiple of 4 otherwise, the HASH digest computation is corrupted.
+ * For the processing of the last buffer of the thread, MDMAT bit must
+ * be reset and the buffer length (in bytes) doesn't have to be a
+ * multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
+}
+
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
+ * DMA transfers to feed the key and the input buffer to the Peripheral.
+ * @note Once the DMA transfers are finished (indicated by hhash->State set back
+ * to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
+ * the computed digest.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note If MDMAT bit is set before calling this function (multi-buffer
+ * HASH processing case), the input buffer size (in bytes) must be
+ * a multiple of 4 otherwise, the HASH digest computation is corrupted.
+ * For the processing of the last buffer of the thread, MDMAT bit must
+ * be reset and the buffer length (in bytes) doesn't have to be a
+ * multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
+ * @brief Peripheral State functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State methods #####
+ ===============================================================================
+ [..]
+ This section permits to get in run-time the state and the peripheral handle
+ status of the peripheral:
+ (+) HAL_HASH_GetState()
+ (+) HAL_HASH_GetStatus()
+
+ [..]
+ Additionally, this subsection provides functions allowing to save and restore
+ the HASH or HMAC processing context in case of calculation suspension:
+ (+) HAL_HASH_ContextSaving()
+ (+) HAL_HASH_ContextRestoring()
+
+ [..]
+ This subsection provides functions allowing to suspend the HASH processing
+ (+) when input are fed to the Peripheral by software
+ (++) HAL_HASH_SwFeed_ProcessSuspend()
+ (+) when input are fed to the Peripheral by DMA
+ (++) HAL_HASH_DMAFeed_ProcessSuspend()
+
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the HASH handle state.
+ * @note The API yields the current state of the handle (BUSY, READY,...).
+ * @param hhash HASH handle.
+ * @retval HAL HASH state
+ */
+HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash)
+{
+ return hhash->State;
+}
+
+
+/**
+ * @brief Return the HASH HAL status.
+ * @note The API yields the HAL status of the handle: it is the result of the
+ * latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
+ * @param hhash HASH handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash)
+{
+ return hhash->Status;
+}
+
+/**
+ * @brief Save the HASH context in case of processing suspension.
+ * @param hhash HASH handle.
+ * @param pMemBuffer pointer to the memory buffer where the HASH context
+ * is saved.
+ * @note The IMR, STR, CR then all the CSR registers are saved
+ * in that order. Only the r/w bits are read to be restored later on.
+ * @note By default, all the context swap registers (there are
+ * HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
+ * @note pMemBuffer points to a buffer allocated by the user. The buffer size
+ * must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
+ * @retval None
+ */
+void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t* pMemBuffer)
+{
+ uint32_t mem_ptr = (uint32_t)pMemBuffer;
+ uint32_t csr_ptr = (uint32_t)HASH->CSR;
+ uint32_t i;
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhash);
+
+ /* Save IMR register content */
+ *(uint32_t*)(mem_ptr) = READ_BIT(HASH->IMR,HASH_IT_DINI|HASH_IT_DCI);
+ mem_ptr+=4U;
+ /* Save STR register content */
+ *(uint32_t*)(mem_ptr) = READ_BIT(HASH->STR,HASH_STR_NBLW);
+ mem_ptr+=4U;
+ /* Save CR register content */
+ *(uint32_t*)(mem_ptr) = READ_BIT(HASH->CR,HASH_CR_DMAE|HASH_CR_DATATYPE|HASH_CR_MODE|HASH_CR_ALGO|HASH_CR_LKEY|HASH_CR_MDMAT);
+ mem_ptr+=4U;
+ /* By default, save all CSRs registers */
+ for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0U; i--)
+ {
+ *(uint32_t*)(mem_ptr) = *(uint32_t*)(csr_ptr);
+ mem_ptr+=4U;
+ csr_ptr+=4U;
+ }
+}
+
+
+/**
+ * @brief Restore the HASH context in case of processing resumption.
+ * @param hhash HASH handle.
+ * @param pMemBuffer pointer to the memory buffer where the HASH context
+ * is stored.
+ * @note The IMR, STR, CR then all the CSR registers are restored
+ * in that order. Only the r/w bits are restored.
+ * @note By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
+ * of those) are restored (all of them have been saved by default
+ * beforehand).
+ * @retval None
+ */
+void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t* pMemBuffer)
+{
+ uint32_t mem_ptr = (uint32_t)pMemBuffer;
+ uint32_t csr_ptr = (uint32_t)HASH->CSR;
+ uint32_t i;
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhash);
+
+ /* Restore IMR register content */
+ WRITE_REG(HASH->IMR, (*(uint32_t*)(mem_ptr)));
+ mem_ptr+=4U;
+ /* Restore STR register content */
+ WRITE_REG(HASH->STR, (*(uint32_t*)(mem_ptr)));
+ mem_ptr+=4U;
+ /* Restore CR register content */
+ WRITE_REG(HASH->CR, (*(uint32_t*)(mem_ptr)));
+ mem_ptr+=4U;
+
+ /* Reset the HASH processor before restoring the Context
+ Swap Registers (CSR) */
+ __HAL_HASH_INIT();
+
+ /* By default, restore all CSR registers */
+ for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0U; i--)
+ {
+ WRITE_REG((*(uint32_t*)(csr_ptr)), (*(uint32_t*)(mem_ptr)));
+ mem_ptr+=4U;
+ csr_ptr+=4U;
+ }
+}
+
+
+/**
+ * @brief Initiate HASH processing suspension when in polling or interruption mode.
+ * @param hhash HASH handle.
+ * @note Set the handle field SuspendRequest to the appropriate value so that
+ * the on-going HASH processing is suspended as soon as the required
+ * conditions are met. Note that the actual suspension is carried out
+ * by the functions HASH_WriteData() in polling mode and HASH_IT() in
+ * interruption mode.
+ * @retval None
+ */
+void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
+{
+ /* Set Handle Suspend Request field */
+ hhash->SuspendRequest = HAL_HASH_SUSPEND;
+}
+
+/**
+ * @brief Suspend the HASH processing when in DMA mode.
+ * @param hhash HASH handle.
+ * @note When suspension attempt occurs at the very end of a DMA transfer and
+ * all the data have already been entered in the Peripheral, hhash->State is
+ * set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
+ * recommended to wrap-up the processing in reading the digest as usual.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
+{
+ uint32_t tmp_remaining_DMATransferSize_inWords;
+ uint32_t tmp_initial_DMATransferSize_inWords;
+ uint32_t tmp_words_already_pushed;
+
+ if (hhash->State == HAL_HASH_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+
+ /* Make sure there is enough time to suspend the processing */
+ tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
+
+ if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT)
+ {
+ /* No suspension attempted since almost to the end of the transferred data. */
+ /* Best option for user code is to wrap up low priority message hashing */
+ return HAL_ERROR;
+ }
+
+ /* Wait for BUSY flag to be reset */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Wait for BUSY flag to be set */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ /* Disable DMA channel */
+ /* Note that the Abort function will
+ - Clear the transfer error flags
+ - Unlock
+ - Set the State
+ */
+ if (HAL_DMA_Abort(hhash->hdmain) !=HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear DMAE bit */
+ CLEAR_BIT(HASH->CR,HASH_CR_DMAE);
+
+ /* Wait for BUSY flag to be reset */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
+ {
+ return HAL_ERROR;
+ }
+
+ /* At this point, DMA interface is disabled and no transfer is on-going */
+ /* Retrieve from the DMA handle how many words remain to be written */
+ tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
+
+ if (tmp_remaining_DMATransferSize_inWords == 0U)
+ {
+ /* All the DMA transfer is actually done. Suspension occurred at the very end
+ of the transfer. Either the digest computation is about to start (HASH case)
+ or processing is about to move from one step to another (HMAC case).
+ In both cases, the processing can't be suspended at this point. It is
+ safer to
+ - retrieve the low priority block digest before starting the high
+ priority block processing (HASH case)
+ - re-attempt a new suspension (HMAC case)
+ */
+ return HAL_ERROR;
+ }
+ else
+ {
+
+ /* Compute how many words were supposed to be transferred by DMA */
+ tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount%4U)!=0U) ? ((hhash->HashInCount+3U)/4U): (hhash->HashInCount/4U));
+
+ /* If discrepancy between the number of words reported by DMA Peripheral and the numbers of words entered as reported
+ by HASH Peripheral, correct it */
+ /* tmp_words_already_pushed reflects the number of words that were already pushed before
+ the start of DMA transfer (multi-buffer processing case) */
+ tmp_words_already_pushed = hhash->NbWordsAlreadyPushed;
+ if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) %16U) != HASH_NBW_PUSHED())
+ {
+ tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */
+ }
+
+ /* Accordingly, update the input pointer that points at the next word to be transferred to the Peripheral by DMA */
+ hhash->pHashInBuffPtr += 4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ;
+
+ /* And store in HashInCount the remaining size to transfer (in bytes) */
+ hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords;
+
+ }
+
+ /* Set State as suspended */
+ hhash->State = HAL_HASH_STATE_SUSPENDED;
+
+ return HAL_OK;
+
+ }
+}
+
+/**
+ * @brief Return the HASH handle error code.
+ * @param hhash pointer to a HASH_HandleTypeDef structure.
+ * @retval HASH Error Code
+*/
+uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash)
+{
+ /* Return HASH Error Code */
+ return hhash->ErrorCode;
+}
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/** @defgroup HASH_Private_Functions HASH Private Functions
+ * @{
+ */
+
+/**
+ * @brief DMA HASH Input Data transfer completion callback.
+ * @param hdma DMA handle.
+ * @note In case of HMAC processing, HASH_DMAXferCplt() initiates
+ * the next DMA transfer for the following HMAC step.
+ * @retval None
+ */
+static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma)
+{
+ HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ uint32_t inputaddr;
+ uint32_t buffersize;
+ HAL_StatusTypeDef status ;
+
+ if (hhash->State != HAL_HASH_STATE_SUSPENDED)
+ {
+
+ /* Disable the DMA transfer */
+ CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
+
+ if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U)
+ {
+ /* If no HMAC processing, input data transfer is now over */
+
+ /* Change the HASH state to ready */
+ hhash->State = HAL_HASH_STATE_READY;
+
+ /* Call Input data transfer complete call back */
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ hhash->InCpltCallback(hhash);
+#else
+ HAL_HASH_InCpltCallback(hhash);
+#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
+
+ }
+ else
+ {
+ /* HMAC processing: depending on the current HMAC step and whether or
+ not multi-buffer processing is on-going, the next step is initiated
+ and MDMAT bit is set. */
+
+
+ if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
+ {
+ /* This is the end of HMAC processing */
+
+ /* Change the HASH state to ready */
+ hhash->State = HAL_HASH_STATE_READY;
+
+ /* Call Input data transfer complete call back
+ (note that the last DMA transfer was that of the key
+ for the outer HASH operation). */
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ hhash->InCpltCallback(hhash);
+#else
+ HAL_HASH_InCpltCallback(hhash);
+#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
+
+ return;
+ }
+ else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
+ {
+ inputaddr = (uint32_t)hhash->pHashMsgBuffPtr; /* DMA transfer start address */
+ buffersize = hhash->HashBuffSize; /* DMA transfer size (in bytes) */
+ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */
+
+ /* In case of suspension request, save the new starting parameters */
+ hhash->HashInCount = hhash->HashBuffSize; /* Initial DMA transfer size (in bytes) */
+ hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr ; /* DMA transfer start address */
+
+ hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */
+ /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */
+ if (hhash->DigestCalculationDisable != RESET)
+ {
+ /* Digest calculation is disabled: Step 2 must start with MDMAT bit set,
+ no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */
+ __HAL_HASH_SET_MDMAT();
+ }
+ }
+ else /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
+ {
+ if (hhash->DigestCalculationDisable != RESET)
+ {
+ /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral
+ (case of multi-buffer HMAC processing):
+ DCAL must not be set.
+ Phase remains in Step 2, MDMAT remains set at this point.
+ Change the HASH state to ready and call Input data transfer complete call back. */
+ hhash->State = HAL_HASH_STATE_READY;
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ hhash->InCpltCallback(hhash);
+#else
+ HAL_HASH_InCpltCallback(hhash);
+#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
+ return ;
+ }
+ else
+ {
+ /* Digest calculation is not disabled (case of single buffer input or last buffer
+ of multi-buffer HMAC processing) */
+ inputaddr = (uint32_t)hhash->Init.pKey; /* DMA transfer start address */
+ buffersize = hhash->Init.KeySize; /* DMA transfer size (in bytes) */
+ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */
+ /* In case of suspension request, save the new starting parameters */
+ hhash->HashInCount = hhash->Init.KeySize; /* Initial size for second DMA transfer (input data) */
+ hhash->pHashInBuffPtr = hhash->Init.pKey ; /* address passed to DMA, now entering data message */
+
+ hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */
+ }
+ }
+
+ /* Configure the Number of valid bits in last word of the message */
+ __HAL_HASH_SET_NBVALIDBITS(buffersize);
+
+ /* Set the HASH DMA transfert completion call back */
+ hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
+
+ /* Enable the DMA In DMA Stream */
+ status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((buffersize %4U)!=0U) ? ((buffersize+(4U-(buffersize %4U)))/4U):(buffersize/4U)));
+
+ /* Enable DMA requests */
+ SET_BIT(HASH->CR, HASH_CR_DMAE);
+
+ /* Return function status */
+ if (status != HAL_OK)
+ {
+ /* Update HASH state machine to error */
+ hhash->State = HAL_HASH_STATE_ERROR;
+ }
+ else
+ {
+ /* Change HASH state */
+ hhash->State = HAL_HASH_STATE_READY;
+ }
+ }
+ }
+
+ return;
+}
+
+/**
+ * @brief DMA HASH communication error callback.
+ * @param hdma DMA handle.
+ * @note HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
+ * can contain user code to manage the error.
+ * @retval None
+ */
+static void HASH_DMAError(DMA_HandleTypeDef *hdma)
+{
+ HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ if (hhash->State != HAL_HASH_STATE_SUSPENDED)
+ {
+ hhash->ErrorCode |= HAL_HASH_ERROR_DMA;
+ /* Set HASH state to ready to prevent any blocking issue in user code
+ present in HAL_HASH_ErrorCallback() */
+ hhash->State= HAL_HASH_STATE_READY;
+ /* Set HASH handle status to error */
+ hhash->Status = HAL_ERROR;
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ hhash->ErrorCallback(hhash);
+#else
+ HAL_HASH_ErrorCallback(hhash);
+#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
+ /* After error handling by code user, reset HASH handle HAL status */
+ hhash->Status = HAL_OK;
+
+ }
+}
+
+/**
+ * @brief Feed the input buffer to the HASH Peripheral.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to input buffer.
+ * @param Size the size of input buffer in bytes.
+ * @note HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
+ * or not the HASH processing must be suspended. If this is the case, the
+ * processing is suspended when possible and the Peripheral feeding point reached at
+ * suspension time is stored in the handle for resumption later on.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ uint32_t buffercounter;
+ __IO uint32_t inputaddr = (uint32_t) pInBuffer;
+
+ for(buffercounter = 0U; buffercounter < Size; buffercounter+=4U)
+ {
+ /* Write input data 4 bytes at a time */
+ HASH->DIN = *(uint32_t*)inputaddr;
+ inputaddr+=4U;
+
+ /* If the suspension flag has been raised and if the processing is not about
+ to end, suspend processing */
+ if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4U) < Size))
+ {
+ /* wait for flag BUSY not set before Wait for DINIS = 1*/
+ if (buffercounter >=64U)
+ {
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
+ in the input buffer */
+ if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
+ {
+ /* Reset SuspendRequest */
+ hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
+
+ /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
+ reached at suspension time is not saved in the same handle fields */
+ if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
+ {
+ /* Save current reading and writing locations of Input and Output buffers */
+ hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
+ /* Save the number of bytes that remain to be processed at this point */
+ hhash->HashInCount = Size - (buffercounter + 4U);
+ }
+ else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
+ {
+ /* Save current reading and writing locations of Input and Output buffers */
+ hhash->pHashKeyBuffPtr = (uint8_t *)inputaddr;
+ /* Save the number of bytes that remain to be processed at this point */
+ hhash->HashKeyCount = Size - (buffercounter + 4U);
+ }
+ else
+ {
+ /* Unexpected phase: unlock process and report error */
+ hhash->State = HAL_HASH_STATE_READY;
+ __HAL_UNLOCK(hhash);
+ return HAL_ERROR;
+ }
+
+ /* Set the HASH state to Suspended and exit to stop entering data */
+ hhash->State = HAL_HASH_STATE_SUSPENDED;
+
+ return HAL_OK;
+ } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) */
+ } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
+ } /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4) */
+
+ /* At this point, all the data have been entered to the Peripheral: exit */
+ return HAL_OK;
+}
+
+/**
+ * @brief Retrieve the message digest.
+ * @param pMsgDigest pointer to the computed digest.
+ * @param Size message digest size in bytes.
+ * @retval None
+ */
+static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
+{
+ uint32_t msgdigest = (uint32_t)pMsgDigest;
+
+ switch(Size)
+ {
+ /* Read the message digest */
+ case 16: /* MD5 */
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
+ break;
+ case 20: /* SHA1 */
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
+ break;
+ case 28: /* SHA224 */
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
+ break;
+ case 32: /* SHA256 */
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
+ msgdigest+=4U;
+ *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+/**
+ * @brief Handle HASH processing Timeout.
+ * @param hhash HASH handle.
+ * @param Flag specifies the HASH flag to check.
+ * @param Status the Flag status (SET or RESET).
+ * @param Timeout Timeout duration.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Wait until flag is set */
+ if(Status == RESET)
+ {
+ while(__HAL_HASH_GET_FLAG(Flag) == RESET)
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Set State to Ready to be able to restart later on */
+ hhash->State = HAL_HASH_STATE_READY;
+ /* Store time out issue in handle status */
+ hhash->Status = HAL_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhash);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+ while(__HAL_HASH_GET_FLAG(Flag) != RESET)
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Set State to Ready to be able to restart later on */
+ hhash->State = HAL_HASH_STATE_READY;
+ /* Store time out issue in handle status */
+ hhash->Status = HAL_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhash);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+
+/**
+ * @brief HASH processing in interruption mode.
+ * @param hhash HASH handle.
+ * @note HASH_IT() regularly reads hhash->SuspendRequest to check whether
+ * or not the HASH processing must be suspended. If this is the case, the
+ * processing is suspended when possible and the Peripheral feeding point reached at
+ * suspension time is stored in the handle for resumption later on.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
+{
+ if (hhash->State == HAL_HASH_STATE_BUSY)
+ {
+ /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
+ if(hhash->HashITCounter == 0U)
+ {
+ /* Disable Interrupts */
+ __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
+ /* HASH state set back to Ready to prevent any issue in user code
+ present in HAL_HASH_ErrorCallback() */
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+ else if (hhash->HashITCounter == 1U)
+ {
+ /* This is the first call to HASH_IT, the first input data are about to be
+ entered in the Peripheral. A specific processing is carried out at this point to
+ start-up the processing. */
+ hhash->HashITCounter = 2U;
+ }
+ else
+ {
+ /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
+ the HASH processing or the end of the current step for HMAC processing. */
+ hhash->HashITCounter = 3U;
+ }
+
+ /* If digest is ready */
+ if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
+ {
+ /* Read the digest */
+ HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
+
+ /* Disable Interrupts */
+ __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_READY;
+ /* Reset HASH state machine */
+ hhash->Phase = HAL_HASH_PHASE_READY;
+ /* Call digest computation complete call back */
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ hhash->DgstCpltCallback(hhash);
+#else
+ HAL_HASH_DgstCpltCallback(hhash);
+#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
+
+ return HAL_OK;
+ }
+
+ /* If Peripheral ready to accept new data */
+ if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
+ {
+
+ /* If the suspension flag has been raised and if the processing is not about
+ to end, suspend processing */
+ if ( (hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
+ {
+ /* Disable Interrupts */
+ __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
+
+ /* Reset SuspendRequest */
+ hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_SUSPENDED;
+
+ return HAL_OK;
+ }
+
+ /* Enter input data in the Peripheral thru HASH_Write_Block_Data() call and
+ check whether the digest calculation has been triggered */
+ if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
+ {
+ /* Call Input data transfer complete call back
+ (called at the end of each step for HMAC) */
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ hhash->InCpltCallback(hhash);
+#else
+ HAL_HASH_InCpltCallback(hhash);
+#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
+
+ if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
+ {
+ /* Wait until Peripheral is not busy anymore */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
+ {
+ /* Disable Interrupts */
+ __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
+ return HAL_TIMEOUT;
+ }
+ /* Initialization start for HMAC STEP 2 */
+ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */
+ __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); /* Set NBLW for the input message */
+ hhash->HashInCount = hhash->HashBuffSize; /* Set the input data size (in bytes) */
+ hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr; /* Set the input data address */
+ hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start of a new phase */
+ __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */
+ }
+ else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
+ {
+ /* Wait until Peripheral is not busy anymore */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
+ {
+ /* Disable Interrupts */
+ __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
+ return HAL_TIMEOUT;
+ }
+ /* Initialization start for HMAC STEP 3 */
+ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */
+ __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); /* Set NBLW for the key */
+ hhash->HashInCount = hhash->Init.KeySize; /* Set the key size (in bytes) */
+ hhash->pHashInBuffPtr = hhash->Init.pKey; /* Set the key address */
+ hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start of a new phase */
+ __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
+ } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+/**
+ * @brief Write a block of data in HASH Peripheral in interruption mode.
+ * @param hhash HASH handle.
+ * @note HASH_Write_Block_Data() is called under interruption by HASH_IT().
+ * @retval HAL status
+ */
+static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
+{
+ uint32_t inputaddr;
+ uint32_t buffercounter;
+ uint32_t inputcounter;
+ uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
+
+ /* If there are more than 64 bytes remaining to be entered */
+ if(hhash->HashInCount > 64U)
+ {
+ inputaddr = (uint32_t)hhash->pHashInBuffPtr;
+ /* Write the Input block in the Data IN register
+ (16 32-bit words, or 64 bytes are entered) */
+ for(buffercounter = 0U; buffercounter < 64U; buffercounter+=4U)
+ {
+ HASH->DIN = *(uint32_t*)inputaddr;
+ inputaddr+=4U;
+ }
+ /* If this is the start of input data entering, an additional word
+ must be entered to start up the HASH processing */
+ if(hhash->HashITCounter == 2U)
+ {
+ HASH->DIN = *(uint32_t*)inputaddr;
+ if(hhash->HashInCount >= 68U)
+ {
+ /* There are still data waiting to be entered in the Peripheral.
+ Decrement buffer counter and set pointer to the proper
+ memory location for the next data entering round. */
+ hhash->HashInCount -= 68U;
+ hhash->pHashInBuffPtr+= 68U;
+ }
+ else
+ {
+ /* All the input buffer has been fed to the HW. */
+ hhash->HashInCount = 0U;
+ }
+ }
+ else
+ {
+ /* 64 bytes have been entered and there are still some remaining:
+ Decrement buffer counter and set pointer to the proper
+ memory location for the next data entering round.*/
+ hhash->HashInCount -= 64U;
+ hhash->pHashInBuffPtr+= 64U;
+ }
+ }
+ else
+ {
+ /* 64 or less bytes remain to be entered. This is the last
+ data entering round. */
+
+ /* Get the buffer address */
+ inputaddr = (uint32_t)hhash->pHashInBuffPtr;
+ /* Get the buffer counter */
+ inputcounter = hhash->HashInCount;
+ /* Disable Interrupts */
+ __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
+
+ /* Write the Input block in the Data IN register */
+ for(buffercounter = 0U; buffercounter < ((inputcounter+3U)/4U); buffercounter++)
+ {
+ HASH->DIN = *(uint32_t*)inputaddr;
+ inputaddr+=4U;
+ }
+
+ if (hhash->Accumulation == 1U)
+ {
+ /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
+ The digest computation will be started when the last buffer data are entered. */
+
+ /* Reset multi buffers accumulation flag */
+ hhash->Accumulation = 0U;
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_READY;
+ /* Call Input data transfer complete call back */
+#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
+ hhash->InCpltCallback(hhash);
+#else
+ HAL_HASH_InCpltCallback(hhash);
+#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Start the Digest calculation */
+ __HAL_HASH_START_DIGEST();
+ /* Return indication that digest calculation has started:
+ this return value triggers the call to Input data transfer
+ complete call back as well as the proper transition from
+ one step to another in HMAC mode. */
+ ret = HASH_DIGEST_CALCULATION_STARTED;
+ }
+ /* Reset buffer counter */
+ hhash->HashInCount = 0;
+ }
+
+ /* Return whether or digest calculation has started */
+ return ret;
+}
+
+/**
+ * @brief HMAC processing in polling mode.
+ * @param hhash HASH handle.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
+{
+ /* Ensure first that Phase is correct */
+ if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3))
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_READY;
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+
+ /* Return function status */
+ return HAL_ERROR;
+ }
+
+ /* HMAC Step 1 processing */
+ if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
+ {
+ /************************** STEP 1 ******************************************/
+ /* Configure the Number of valid bits in last word of the message */
+ __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
+
+ /* Write input buffer in Data register */
+ hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
+ if (hhash->Status != HAL_OK)
+ {
+ return hhash->Status;
+ }
+
+ /* Check whether or not key entering process has been suspended */
+ if (hhash->State == HAL_HASH_STATE_SUSPENDED)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhash);
+
+ /* Stop right there and return function status */
+ return HAL_OK;
+ }
+
+ /* No processing suspension at this point: set DCAL bit. */
+ __HAL_HASH_START_DIGEST();
+
+ /* Wait for BUSY flag to be cleared */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Move from Step 1 to Step 2 */
+ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
+
+ }
+
+ /* HMAC Step 2 processing.
+ After phase check, HMAC_Processing() may
+ - directly start up from this point in resumption case
+ if the same Step 2 processing was suspended previously
+ - or fall through from the Step 1 processing carried out hereabove */
+ if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
+ {
+ /************************** STEP 2 ******************************************/
+ /* Configure the Number of valid bits in last word of the message */
+ __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
+
+ /* Write input buffer in Data register */
+ hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
+ if (hhash->Status != HAL_OK)
+ {
+ return hhash->Status;
+ }
+
+ /* Check whether or not data entering process has been suspended */
+ if (hhash->State == HAL_HASH_STATE_SUSPENDED)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhash);
+
+ /* Stop right there and return function status */
+ return HAL_OK;
+ }
+
+ /* No processing suspension at this point: set DCAL bit. */
+ __HAL_HASH_START_DIGEST();
+
+ /* Wait for BUSY flag to be cleared */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Move from Step 2 to Step 3 */
+ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
+ /* In case Step 1 phase was suspended then resumed,
+ set again Key input buffers and size before moving to
+ next step */
+ hhash->pHashKeyBuffPtr = hhash->Init.pKey;
+ hhash->HashKeyCount = hhash->Init.KeySize;
+ }
+
+
+ /* HMAC Step 3 processing.
+ After phase check, HMAC_Processing() may
+ - directly start up from this point in resumption case
+ if the same Step 3 processing was suspended previously
+ - or fall through from the Step 2 processing carried out hereabove */
+ if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
+ {
+ /************************** STEP 3 ******************************************/
+ /* Configure the Number of valid bits in last word of the message */
+ __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
+
+ /* Write input buffer in Data register */
+ hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
+ if (hhash->Status != HAL_OK)
+ {
+ return hhash->Status;
+ }
+
+ /* Check whether or not key entering process has been suspended */
+ if (hhash->State == HAL_HASH_STATE_SUSPENDED)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhash);
+
+ /* Stop right there and return function status */
+ return HAL_OK;
+ }
+
+ /* No processing suspension at this point: start the Digest calculation. */
+ __HAL_HASH_START_DIGEST();
+
+ /* Wait for DCIS flag to be set */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Read the message digest */
+ HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
+
+ /* Reset HASH state machine */
+ hhash->Phase = HAL_HASH_PHASE_READY;
+ }
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_READY;
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Initialize the HASH peripheral, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest.
+ * @param Timeout Timeout value.
+ * @param Algorithm HASH algorithm.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout, uint32_t Algorithm)
+{
+ uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */
+ uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
+ HAL_HASH_StateTypeDef State_tmp = hhash->State;
+
+
+ /* Initiate HASH processing in case of start or resumption */
+if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
+ {
+ /* Check input parameters */
+ if ((pInBuffer == NULL) || (pOutBuffer == NULL))
+ {
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhash);
+
+ /* Check if initialization phase has not been already performed */
+ if(hhash->Phase == HAL_HASH_PHASE_READY)
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
+ MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
+
+ /* Configure the number of valid bits in last word of the message */
+ __HAL_HASH_SET_NBVALIDBITS(Size);
+
+ /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
+ input parameters of HASH_WriteData() */
+ pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */
+ Size_tmp = Size; /* Size_tmp contains the input data size in bytes */
+
+ /* Set the phase */
+ hhash->Phase = HAL_HASH_PHASE_PROCESS;
+ }
+ else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
+ {
+ /* if the Peripheral has already been initialized, two cases are possible */
+
+ /* Process resumption time ... */
+ if (hhash->State == HAL_HASH_STATE_SUSPENDED)
+ {
+ /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
+ to the API input parameters but to those saved beforehand by HASH_WriteData()
+ when the processing was suspended */
+ pInBuffer_tmp = hhash->pHashInBuffPtr;
+ Size_tmp = hhash->HashInCount;
+ }
+ /* ... or multi-buffer HASH processing end */
+ else
+ {
+ /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
+ input parameters of HASH_WriteData() */
+ pInBuffer_tmp = pInBuffer;
+ Size_tmp = Size;
+ /* Configure the number of valid bits in last word of the message */
+ __HAL_HASH_SET_NBVALIDBITS(Size);
+ }
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+ }
+ else
+ {
+ /* Phase error */
+ hhash->State = HAL_HASH_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhash);
+
+ /* Return function status */
+ return HAL_ERROR;
+ }
+
+
+ /* Write input buffer in Data register */
+ hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
+ if (hhash->Status != HAL_OK)
+ {
+ return hhash->Status;
+ }
+
+ /* If the process has not been suspended, carry on to digest calculation */
+ if (hhash->State != HAL_HASH_STATE_SUSPENDED)
+ {
+ /* Start the Digest calculation */
+ __HAL_HASH_START_DIGEST();
+
+ /* Wait for DCIS flag to be set */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Read the message digest */
+ HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_READY;
+
+ /* Reset HASH state machine */
+ hhash->Phase = HAL_HASH_PHASE_READY;
+
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhash);
+
+ /* Return function status */
+ return HAL_OK;
+
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+/**
+ * @brief If not already done, initialize the HASH peripheral then
+ * processes pInBuffer.
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @param Algorithm HASH algorithm.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
+{
+ uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */
+ uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
+ HAL_HASH_StateTypeDef State_tmp = hhash->State;
+
+ /* Make sure the input buffer size (in bytes) is a multiple of 4 */
+ if ((Size % 4U) != 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Initiate HASH processing in case of start or resumption */
+if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
+ {
+ /* Check input parameters */
+ if ((pInBuffer == NULL) || (Size == 0U))
+ {
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhash);
+
+ /* If resuming the HASH processing */
+ if (hhash->State == HAL_HASH_STATE_SUSPENDED)
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
+ to the API input parameters but to those saved beforehand by HASH_WriteData()
+ when the processing was suspended */
+ pInBuffer_tmp = hhash->pHashInBuffPtr; /* pInBuffer_tmp is set to the input data address */
+ Size_tmp = hhash->HashInCount; /* Size_tmp contains the input data size in bytes */
+
+ }
+ else
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
+ input parameters of HASH_WriteData() */
+ pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */
+ Size_tmp = Size; /* Size_tmp contains the input data size in bytes */
+
+ /* Check if initialization phase has already be performed */
+ if(hhash->Phase == HAL_HASH_PHASE_READY)
+ {
+ /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
+ MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
+ }
+
+ /* Set the phase */
+ hhash->Phase = HAL_HASH_PHASE_PROCESS;
+
+ }
+
+ /* Write input buffer in Data register */
+ hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
+ if (hhash->Status != HAL_OK)
+ {
+ return hhash->Status;
+ }
+
+ /* If the process has not been suspended, move the state to Ready */
+ if (hhash->State != HAL_HASH_STATE_SUSPENDED)
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_READY;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhash);
+
+ /* Return function status */
+ return HAL_OK;
+
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+
+}
+
+
+/**
+ * @brief If not already done, initialize the HASH peripheral then
+ * processes pInBuffer in interruption mode.
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @param Algorithm HASH algorithm.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
+{
+ HAL_HASH_StateTypeDef State_tmp = hhash->State;
+ __IO uint32_t inputaddr = (uint32_t) pInBuffer;
+ uint32_t SizeVar = Size;
+
+ /* Make sure the input buffer size (in bytes) is a multiple of 4 */
+ if ((Size % 4U) != 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Initiate HASH processing in case of start or resumption */
+ if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
+ {
+ /* Check input parameters */
+ if ((pInBuffer == NULL) || (Size == 0U))
+ {
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhash);
+
+ /* If resuming the HASH processing */
+ if (hhash->State == HAL_HASH_STATE_SUSPENDED)
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+ }
+ else
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Check if initialization phase has already be performed */
+ if(hhash->Phase == HAL_HASH_PHASE_READY)
+ {
+ /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
+ MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
+ hhash->HashITCounter = 1;
+ }
+ else
+ {
+ hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
+ }
+
+ /* Set the phase */
+ hhash->Phase = HAL_HASH_PHASE_PROCESS;
+
+ /* If DINIS is equal to 0 (for example if an incomplete block has been previously
+ fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
+ Therefore, first words are manually entered until DINIS raises, or until there
+ is not more data to enter. */
+ while((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U))
+ {
+
+ /* Write input data 4 bytes at a time */
+ HASH->DIN = *(uint32_t*)inputaddr;
+ inputaddr+=4U;
+ SizeVar-=4U;
+ }
+
+ /* If DINIS is still not set or if all the data have been fed, stop here */
+ if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U))
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_READY;
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+
+ /* otherwise, carry on in interrupt-mode */
+ hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data
+ to be fed to the Peripheral */
+ hhash->pHashInBuffPtr = (uint8_t *)inputaddr; /* Points at data which will be fed to the Peripheral at
+ the next interruption */
+ /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
+ the information describing where the HASH process is stopped.
+ These variables are used later on to resume the HASH processing at the
+ correct location. */
+
+ }
+
+ /* Set multi buffers accumulation flag */
+ hhash->Accumulation = 1U;
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+
+ /* Enable Data Input interrupt */
+ __HAL_HASH_ENABLE_IT(HASH_IT_DINI);
+
+ /* Return function status */
+ return HAL_OK;
+
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+}
+
+
+
+/**
+ * @brief Initialize the HASH peripheral, next process pInBuffer then
+ * read the computed digest in interruption mode.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest.
+ * @param Algorithm HASH algorithm.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Algorithm)
+{
+ HAL_HASH_StateTypeDef State_tmp = hhash->State;
+ __IO uint32_t inputaddr = (uint32_t) pInBuffer;
+ uint32_t polling_step = 0U;
+ uint32_t initialization_skipped = 0U;
+ uint32_t SizeVar = Size;
+
+ /* If State is ready or suspended, start or resume IT-based HASH processing */
+if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
+ {
+ /* Check input parameters */
+ if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
+ {
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhash);
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Initialize IT counter */
+ hhash->HashITCounter = 1;
+
+ /* Check if initialization phase has already be performed */
+ if(hhash->Phase == HAL_HASH_PHASE_READY)
+ {
+ /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
+ MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
+
+ /* Configure the number of valid bits in last word of the message */
+ __HAL_HASH_SET_NBVALIDBITS(SizeVar);
+
+
+ hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data
+ to be fed to the Peripheral */
+ hhash->pHashInBuffPtr = pInBuffer; /* Points at data which will be fed to the Peripheral at
+ the next interruption */
+ /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
+ the information describing where the HASH process is stopped.
+ These variables are used later on to resume the HASH processing at the
+ correct location. */
+
+ hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
+ }
+ else
+ {
+ initialization_skipped = 1; /* info user later on in case of multi-buffer */
+ }
+
+ /* Set the phase */
+ hhash->Phase = HAL_HASH_PHASE_PROCESS;
+
+ /* If DINIS is equal to 0 (for example if an incomplete block has been previously
+ fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
+ Therefore, first words are manually entered until DINIS raises. */
+ while((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U))
+ {
+ polling_step = 1U; /* note that some words are entered before enabling the interrupt */
+
+ /* Write input data 4 bytes at a time */
+ HASH->DIN = *(uint32_t*)inputaddr;
+ inputaddr+=4U;
+ SizeVar-=4U;
+ }
+
+ if (polling_step == 1U)
+ {
+ if (SizeVar == 0U)
+ {
+ /* If all the data have been entered at this point, it only remains to
+ read the digest */
+ hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
+
+ /* Start the Digest calculation */
+ __HAL_HASH_START_DIGEST();
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+
+ /* Enable Interrupts */
+ __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
+ {
+ /* It remains data to enter and the Peripheral is ready to trigger DINIE,
+ carry on as usual.
+ Update HashInCount and pHashInBuffPtr accordingly. */
+ hhash->HashInCount = SizeVar;
+ hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
+ __HAL_HASH_SET_NBVALIDBITS(SizeVar); /* Update the configuration of the number of valid bits in last word of the message */
+ hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
+ if (initialization_skipped == 1U)
+ {
+ hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
+ }
+ }
+ else
+ {
+ /* DINIS is not set but it remains a few data to enter (not enough for a full word).
+ Manually enter the last bytes before enabling DCIE. */
+ __HAL_HASH_SET_NBVALIDBITS(SizeVar);
+ HASH->DIN = *(uint32_t*)inputaddr;
+
+ /* Start the Digest calculation */
+ hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
+ __HAL_HASH_START_DIGEST();
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+
+ /* Enable Interrupts */
+ __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ } /* if (polling_step == 1) */
+
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+
+ /* Enable Interrupts */
+ __HAL_HASH_ENABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+}
+
+
+/**
+ * @brief Initialize the HASH peripheral then initiate a DMA transfer
+ * to feed the input buffer to the Peripheral.
+ * @note If MDMAT bit is set before calling this function (multi-buffer
+ * HASH processing case), the input buffer size (in bytes) must be
+ * a multiple of 4 otherwise, the HASH digest computation is corrupted.
+ * For the processing of the last buffer of the thread, MDMAT bit must
+ * be reset and the buffer length (in bytes) doesn't have to be a
+ * multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param Algorithm HASH algorithm.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
+{
+ uint32_t inputaddr;
+ uint32_t inputSize;
+ HAL_StatusTypeDef status ;
+ HAL_HASH_StateTypeDef State_tmp = hhash->State;
+
+
+ /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
+ (case of multi-buffer HASH processing) */
+ assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
+
+ /* If State is ready or suspended, start or resume polling-based HASH processing */
+if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
+ {
+ /* Check input parameters */
+ if ( (pInBuffer == NULL ) || (Size == 0U) ||
+ /* Check phase coherency. Phase must be
+ either READY (fresh start)
+ or PROCESS (multi-buffer HASH management) */
+ ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
+ {
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+
+
+ /* Process Locked */
+ __HAL_LOCK(hhash);
+
+ /* If not a resumption case */
+ if (hhash->State == HAL_HASH_STATE_READY)
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Check if initialization phase has already been performed.
+ If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
+ API is processing a new input data message in case of multi-buffer HASH
+ computation. */
+ if(hhash->Phase == HAL_HASH_PHASE_READY)
+ {
+ /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
+ MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
+
+ /* Set the phase */
+ hhash->Phase = HAL_HASH_PHASE_PROCESS;
+ }
+
+ /* Configure the Number of valid bits in last word of the message */
+ __HAL_HASH_SET_NBVALIDBITS(Size);
+
+ inputaddr = (uint32_t)pInBuffer; /* DMA transfer start address */
+ inputSize = Size; /* DMA transfer size (in bytes) */
+
+ /* In case of suspension request, save the starting parameters */
+ hhash->pHashInBuffPtr = pInBuffer; /* DMA transfer start address */
+ hhash->HashInCount = Size; /* DMA transfer size (in bytes) */
+
+ }
+ /* If resumption case */
+ else
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Resumption case, inputaddr and inputSize are not set to the API input parameters
+ but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
+ processing was suspended */
+ inputaddr = (uint32_t)hhash->pHashInBuffPtr; /* DMA transfer start address */
+ inputSize = hhash->HashInCount; /* DMA transfer size (in bytes) */
+
+ }
+
+ /* Set the HASH DMA transfert complete callback */
+ hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
+ /* Set the DMA error callback */
+ hhash->hdmain->XferErrorCallback = HASH_DMAError;
+
+ /* Store number of words already pushed to manage proper DMA processing suspension */
+ hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
+
+ /* Enable the DMA In DMA Stream */
+ status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((inputSize %4U)!=0U) ? ((inputSize+(4U-(inputSize %4U)))/4U):(inputSize/4U)));
+
+ /* Enable DMA requests */
+ SET_BIT(HASH->CR, HASH_CR_DMAE);
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+
+ /* Return function status */
+ if (status != HAL_OK)
+ {
+ /* Update HASH state machine to error */
+ hhash->State = HAL_HASH_STATE_ERROR;
+ }
+
+ return status;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Return the computed digest.
+ * @note The API waits for DCIS to be set then reads the computed digest.
+ * @param hhash HASH handle.
+ * @param pOutBuffer pointer to the computed digest.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+
+ if(hhash->State == HAL_HASH_STATE_READY)
+ {
+ /* Check parameter */
+ if (pOutBuffer == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhash);
+
+ /* Change the HASH state to busy */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Wait for DCIS flag to be set */
+ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Read the message digest */
+ HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
+
+ /* Change the HASH state to ready */
+ hhash->State = HAL_HASH_STATE_READY;
+
+ /* Reset HASH state machine */
+ hhash->Phase = HAL_HASH_PHASE_READY;
+
+ /* Process UnLock */
+ __HAL_UNLOCK(hhash);
+
+ /* Return function status */
+ return HAL_OK;
+
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+}
+
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest.
+ * @param Timeout Timeout value.
+ * @param Algorithm HASH algorithm.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout, uint32_t Algorithm)
+{
+ HAL_HASH_StateTypeDef State_tmp = hhash->State;
+
+ /* If State is ready or suspended, start or resume polling-based HASH processing */
+if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
+ {
+ /* Check input parameters */
+ if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || (pOutBuffer == NULL))
+ {
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhash);
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Check if initialization phase has already be performed */
+ if(hhash->Phase == HAL_HASH_PHASE_READY)
+ {
+ /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
+ if(hhash->Init.KeySize > 64U)
+ {
+ MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
+ }
+ else
+ {
+ MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
+ }
+ /* Set the phase to Step 1 */
+ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
+ /* Resort to hhash internal fields to feed the Peripheral.
+ Parameters will be updated in case of suspension to contain the proper
+ information at resumption time. */
+ hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */
+ hhash->pHashInBuffPtr = pInBuffer; /* Input data address, HMAC_Processing input parameter for Step 2 */
+ hhash->HashInCount = Size; /* Input data size, HMAC_Processing input parameter for Step 2 */
+ hhash->HashBuffSize = Size; /* Store the input buffer size for the whole HMAC process */
+ hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address, HMAC_Processing input parameter for Step 1 and Step 3 */
+ hhash->HashKeyCount = hhash->Init.KeySize; /* Key size, HMAC_Processing input parameter for Step 1 and Step 3 */
+ }
+
+ /* Carry out HMAC processing */
+ return HMAC_Processing(hhash, Timeout);
+
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
+ * read the computed digest in interruption mode.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest.
+ * @param Algorithm HASH algorithm.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Algorithm)
+{
+ HAL_HASH_StateTypeDef State_tmp = hhash->State;
+
+ /* If State is ready or suspended, start or resume IT-based HASH processing */
+if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
+ {
+ /* Check input parameters */
+ if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || (pOutBuffer == NULL))
+ {
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhash);
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Initialize IT counter */
+ hhash->HashITCounter = 1;
+
+ /* Check if initialization phase has already be performed */
+ if (hhash->Phase == HAL_HASH_PHASE_READY)
+ {
+ /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
+ if(hhash->Init.KeySize > 64U)
+ {
+ MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
+ }
+ else
+ {
+ MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
+ }
+
+ /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
+ to feed the Peripheral whatever the HMAC step.
+ Lines below are set to start HMAC Step 1 processing where key is entered first. */
+ hhash->HashInCount = hhash->Init.KeySize; /* Key size */
+ hhash->pHashInBuffPtr = hhash->Init.pKey ; /* Key address */
+
+ /* Store input and output parameters in handle fields to manage steps transition
+ or possible HMAC suspension/resumption */
+ hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */
+ hhash->pHashMsgBuffPtr = pInBuffer; /* Input message address */
+ hhash->HashBuffSize = Size; /* Input message size (in bytes) */
+ hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */
+
+ /* Configure the number of valid bits in last word of the key */
+ __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
+
+ /* Set the phase to Step 1 */
+ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
+ }
+ else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
+ {
+ /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
+
+ }
+ else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
+ {
+ /* Restart IT-based HASH processing after Step 2 suspension */
+
+ }
+ else
+ {
+ /* Error report as phase incorrect */
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hhash);
+
+ /* Enable Interrupts */
+ __HAL_HASH_ENABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+}
+
+
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC mode then initiate the required
+ * DMA transfers to feed the key and the input buffer to the Peripheral.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
+ * be a multiple of 4 otherwise, the HASH digest computation is corrupted.
+ * Only the length of the last buffer of the thread doesn't have to be a
+ * multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param Algorithm HASH algorithm.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
+{
+ uint32_t inputaddr;
+ uint32_t inputSize;
+ HAL_StatusTypeDef status ;
+ HAL_HASH_StateTypeDef State_tmp = hhash->State;
+ /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
+ is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
+ assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size));
+ /* If State is ready or suspended, start or resume DMA-based HASH processing */
+if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
+ {
+ /* Check input parameters */
+ if ((pInBuffer == NULL ) || (Size == 0U) || (hhash->Init.pKey == NULL ) || (hhash->Init.KeySize == 0U) ||
+ /* Check phase coherency. Phase must be
+ either READY (fresh start)
+ or one of HMAC PROCESS steps (multi-buffer HASH management) */
+ ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
+ {
+ hhash->State = HAL_HASH_STATE_READY;
+ return HAL_ERROR;
+ }
+
+
+ /* Process Locked */
+ __HAL_LOCK(hhash);
+
+ /* If not a case of resumption after suspension */
+ if (hhash->State == HAL_HASH_STATE_READY)
+ {
+ /* Check whether or not initialization phase has already be performed */
+ if(hhash->Phase == HAL_HASH_PHASE_READY)
+ {
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+ /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
+ At the same time, ensure MDMAT bit is cleared. */
+ if(hhash->Init.KeySize > 64U)
+ {
+ MODIFY_REG(HASH->CR, HASH_CR_MDMAT|HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
+ }
+ else
+ {
+ MODIFY_REG(HASH->CR, HASH_CR_MDMAT|HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
+ }
+ /* Store input aparameters in handle fields to manage steps transition
+ or possible HMAC suspension/resumption */
+ hhash->HashInCount = hhash->Init.KeySize; /* Initial size for first DMA transfer (key size) */
+ hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */
+ hhash->pHashInBuffPtr = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
+ hhash->pHashMsgBuffPtr = pInBuffer; /* Input data address */
+ hhash->HashBuffSize = Size; /* input data size (in bytes) */
+
+ /* Set DMA input parameters */
+ inputaddr = (uint32_t)(hhash->Init.pKey); /* Address passed to DMA (start by entering Key message) */
+ inputSize = hhash->Init.KeySize; /* Size for first DMA transfer (in bytes) */
+
+ /* Configure the number of valid bits in last word of the key */
+ __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
+
+ /* Set the phase to Step 1 */
+ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
+
+ }
+ else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
+ {
+ /* Process a new input data message in case of multi-buffer HMAC processing
+ (this is not a resumption case) */
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Save input parameters to be able to manage possible suspension/resumption */
+ hhash->HashInCount = Size; /* Input message address */
+ hhash->pHashInBuffPtr = pInBuffer; /* Input message size in bytes */
+
+ /* Set DMA input parameters */
+ inputaddr = (uint32_t)pInBuffer; /* Input message address */
+ inputSize = Size; /* Input message size in bytes */
+
+ if (hhash->DigestCalculationDisable == RESET)
+ {
+ /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
+ __HAL_HASH_RESET_MDMAT();
+ __HAL_HASH_SET_NBVALIDBITS(inputSize);
+ }
+ }
+ else
+ {
+ /* Phase not aligned with handle READY state */
+ __HAL_UNLOCK(hhash);
+ /* Return function status */
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Resumption case (phase may be Step 1, 2 or 3) */
+
+ /* Change the HASH state */
+ hhash->State = HAL_HASH_STATE_BUSY;
+
+ /* Set DMA input parameters at resumption location;
+ inputaddr and inputSize are not set to the API input parameters
+ but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
+ processing was suspended. */
+ inputaddr = (uint32_t)(hhash->pHashInBuffPtr); /* Input message address */
+ inputSize = hhash->HashInCount; /* Input message size in bytes */
+ }
+
+
+ /* Set the HASH DMA transfert complete callback */
+ hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
+ /* Set the DMA error callback */
+ hhash->hdmain->XferErrorCallback = HASH_DMAError;
+
+ /* Store number of words already pushed to manage proper DMA processing suspension */
+ hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
+
+ /* Enable the DMA In DMA Stream */
+ status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((inputSize %4U)!=0U) ? ((inputSize+(4U-(inputSize %4U)))/4U):(inputSize/4U)));
+ /* Enable DMA requests */
+ SET_BIT(HASH->CR, HASH_CR_DMAE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhash);
+
+ /* Return function status */
+ if (status != HAL_OK)
+ {
+ /* Update HASH state machine to error */
+ hhash->State = HAL_HASH_STATE_ERROR;
+ }
+
+ /* Return function status */
+ return status;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @}
+ */
+
+#endif /* HAL_HASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+#endif /* HASH*/
+/**
+ * @}
+ */
+
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_hash_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hash_ex.c
new file mode 100644
index 0000000000..13939d6151
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hash_ex.c
@@ -0,0 +1,1030 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_hash_ex.c
+ * @author MCD Application Team
+ * @brief Extended HASH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the HASH peripheral for SHA-224 and SHA-256
+ * alogrithms:
+ * + HASH or HMAC processing in polling mode
+ * + HASH or HMAC processing in interrupt mode
+ * + HASH or HMAC processing in DMA mode
+ * Additionally, this file provides functions to manage HMAC
+ * multi-buffer DMA-based processing for MD-5, SHA-1, SHA-224
+ * and SHA-256.
+ *
+ *
+ @verbatim
+ ===============================================================================
+ ##### HASH peripheral extended features #####
+ ===============================================================================
+ [..]
+ The SHA-224 and SHA-256 HASH and HMAC processing can be carried out exactly
+ the same way as for SHA-1 or MD-5 algorithms.
+ (#) Three modes are available.
+ (##) Polling mode: processing APIs are blocking functions
+ i.e. they process the data and wait till the digest computation is finished,
+ e.g. HAL_HASHEx_xxx_Start()
+ (##) Interrupt mode: processing APIs are not blocking functions
+ i.e. they process the data under interrupt,
+ e.g. HAL_HASHEx_xxx_Start_IT()
+ (##) DMA mode: processing APIs are not blocking functions and the CPU is
+ not used for data transfer i.e. the data transfer is ensured by DMA,
+ e.g. HAL_HASHEx_xxx_Start_DMA(). Note that in DMA mode, a call to
+ HAL_HASHEx_xxx_Finish() is then required to retrieve the digest.
+
+ (#)Multi-buffer processing is possible in polling, interrupt and DMA modes.
+ (##) In polling mode, only multi-buffer HASH processing is possible.
+ API HAL_HASHEx_xxx_Accumulate() must be called for each input buffer, except for the last one.
+ User must resort to HAL_HASHEx_xxx_Accumulate_End() to enter the last one and retrieve as
+ well the computed digest.
+
+ (##) In interrupt mode, API HAL_HASHEx_xxx_Accumulate_IT() must be called for each input buffer,
+ except for the last one.
+ User must resort to HAL_HASHEx_xxx_Accumulate_End_IT() to enter the last one and retrieve as
+ well the computed digest.
+
+ (##) In DMA mode, multi-buffer HASH and HMAC processing are possible.
+
+ (+++) HASH processing: once initialization is done, MDMAT bit must be set thru __HAL_HASH_SET_MDMAT() macro.
+ From that point, each buffer can be fed to the Peripheral thru HAL_HASHEx_xxx_Start_DMA() API.
+ Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT()
+ macro then wrap-up the HASH processing in feeding the last input buffer thru the
+ same API HAL_HASHEx_xxx_Start_DMA(). The digest can then be retrieved with a call to
+ API HAL_HASHEx_xxx_Finish().
+
+ (+++) HMAC processing (MD-5, SHA-1, SHA-224 and SHA-256 must all resort to
+ extended functions): after initialization, the key and the first input buffer are entered
+ in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
+ starts step 2.
+ The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this
+ point, the HMAC processing is still carrying out step 2.
+ Then, step 2 for the last input buffer and step 3 are carried out by a single call
+ to HAL_HMACEx_xxx_Step2_3_DMA().
+
+ The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish() for
+ MD-5 and SHA-1, to HAL_HASHEx_xxx_Finish() for SHA-224 and SHA-256.
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+
+
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#if defined (HASH)
+
+/** @defgroup HASHEx HASHEx
+ * @brief HASH HAL extended module driver.
+ * @{
+ */
+#ifdef HAL_HASH_MODULE_ENABLED
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+
+/** @defgroup HASHEx_Exported_Functions HASH Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup HASHEx_Exported_Functions_Group1 HASH extended processing functions in polling mode
+ * @brief HASH extended processing functions using polling mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### Polling mode HASH extended processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in polling mode
+ the hash value using one of the following algorithms:
+ (+) SHA224
+ (++) HAL_HASHEx_SHA224_Start()
+ (++) HAL_HASHEx_SHA224_Accmlt()
+ (++) HAL_HASHEx_SHA224_Accmlt_End()
+ (+) SHA256
+ (++) HAL_HASHEx_SHA256_Start()
+ (++) HAL_HASHEx_SHA256_Accmlt()
+ (++) HAL_HASHEx_SHA256_Accmlt_End()
+
+ [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
+
+ [..] In case of multi-buffer HASH processing (a single digest is computed while
+ several buffers are fed to the Peripheral), the user can resort to successive calls
+ to HAL_HASHEx_xxx_Accumulate() and wrap-up the digest computation by a call
+ to HAL_HASHEx_xxx_Accumulate_End().
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Initialize the HASH peripheral in SHA224 mode, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes.
+ * @param Timeout Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief If not already done, initialize the HASH peripheral in SHA224 mode then
+ * processes pInBuffer.
+ * @note Consecutive calls to HAL_HASHEx_SHA224_Accmlt() can be used to feed
+ * several input buffers back-to-back to the Peripheral that will yield a single
+ * HASH signature once all buffers have been entered. Wrap-up of input
+ * buffers feeding and retrieval of digest is done by a call to
+ * HAL_HASHEx_SHA224_Accmlt_End().
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note Digest is not retrieved by this API, user must resort to HAL_HASHEx_SHA224_Accmlt_End()
+ * to read it, feeding at the same time the last input buffer to the Peripheral.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted. Only HAL_HASHEx_SHA224_Accmlt_End() is able
+ * to manage the ending buffer with a length in bytes not a multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief End computation of a single HASH signature after several calls to HAL_HASHEx_SHA224_Accmlt() API.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes.
+ * @param Timeout Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in SHA256 mode, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes.
+ * @param Timeout Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @brief If not already done, initialize the HASH peripheral in SHA256 mode then
+ * processes pInBuffer.
+ * @note Consecutive calls to HAL_HASHEx_SHA256_Accmlt() can be used to feed
+ * several input buffers back-to-back to the Peripheral that will yield a single
+ * HASH signature once all buffers have been entered. Wrap-up of input
+ * buffers feeding and retrieval of digest is done by a call to
+ * HAL_HASHEx_SHA256_Accmlt_End().
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note Digest is not retrieved by this API, user must resort to HAL_HASHEx_SHA256_Accmlt_End()
+ * to read it, feeding at the same time the last input buffer to the Peripheral.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted. Only HAL_HASHEx_SHA256_Accmlt_End() is able
+ * to manage the ending buffer with a length in bytes not a multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @brief End computation of a single HASH signature after several calls to HAL_HASHEx_SHA256_Accmlt() API.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes.
+ * @param Timeout Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HASHEx_Exported_Functions_Group2 HASH extended processing functions in interrupt mode
+ * @brief HASH extended processing functions using interrupt mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### Interruption mode HASH extended processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in interrupt mode
+ the hash value using one of the following algorithms:
+ (+) SHA224
+ (++) HAL_HASHEx_SHA224_Start_IT()
+ (++) HAL_HASHEx_SHA224_Accmlt_IT()
+ (++) HAL_HASHEx_SHA224_Accmlt_End_IT()
+ (+) SHA256
+ (++) HAL_HASHEx_SHA256_Start_IT()
+ (++) HAL_HASHEx_SHA256_Accmlt_IT()
+ (++) HAL_HASHEx_SHA256_Accmlt_End_IT()
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Initialize the HASH peripheral in SHA224 mode, next process pInBuffer then
+ * read the computed digest in interruption mode.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief If not already done, initialize the HASH peripheral in SHA224 mode then
+ * processes pInBuffer in interruption mode.
+ * @note Consecutive calls to HAL_HASHEx_SHA224_Accmlt_IT() can be used to feed
+ * several input buffers back-to-back to the Peripheral that will yield a single
+ * HASH signature once all buffers have been entered. Wrap-up of input
+ * buffers feeding and retrieval of digest is done by a call to
+ * HAL_HASHEx_SHA224_Accmlt_End_IT().
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted. Only HAL_HASHEx_SHA224_Accmlt_End_IT() is able
+ * to manage the ending buffer with a length in bytes not a multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Accumulate_IT(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief End computation of a single HASH signature after several calls to HAL_HASHEx_SHA224_Accmlt_IT() API.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in SHA256 mode, next process pInBuffer then
+ * read the computed digest in interruption mode.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @brief If not already done, initialize the HASH peripheral in SHA256 mode then
+ * processes pInBuffer in interruption mode.
+ * @note Consecutive calls to HAL_HASHEx_SHA256_Accmlt_IT() can be used to feed
+ * several input buffers back-to-back to the Peripheral that will yield a single
+ * HASH signature once all buffers have been entered. Wrap-up of input
+ * buffers feeding and retrieval of digest is done by a call to
+ * HAL_HASHEx_SHA256_Accmlt_End_IT().
+ * @note Field hhash->Phase of HASH handle is tested to check whether or not
+ * the Peripheral has already been initialized.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted. Only HAL_HASHEx_SHA256_Accmlt_End_IT() is able
+ * to manage the ending buffer with a length in bytes not a multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes, must be a multiple of 4.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Accumulate_IT(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @brief End computation of a single HASH signature after several calls to HAL_HASHEx_SHA256_Accmlt_IT() API.
+ * @note Digest is available in pOutBuffer.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HASHEx_Exported_Functions_Group3 HASH extended processing functions in DMA mode
+ * @brief HASH extended processing functions using DMA mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### DMA mode HASH extended processing functionss #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in DMA mode
+ the hash value using one of the following algorithms:
+ (+) SHA224
+ (++) HAL_HASHEx_SHA224_Start_DMA()
+ (++) HAL_HASHEx_SHA224_Finish()
+ (+) SHA256
+ (++) HAL_HASHEx_SHA256_Start_DMA()
+ (++) HAL_HASHEx_SHA256_Finish()
+
+ [..] When resorting to DMA mode to enter the data in the Peripheral, user must resort
+ to HAL_HASHEx_xxx_Start_DMA() then read the resulting digest with
+ HAL_HASHEx_xxx_Finish().
+
+ [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before
+ the successive calls to HAL_HASHEx_xxx_Start_DMA(). Then, MDMAT bit needs to be
+ reset before the last call to HAL_HASHEx_xxx_Start_DMA(). Digest is finally
+ retrieved thanks to HAL_HASHEx_xxx_Finish().
+
+@endverbatim
+ * @{
+ */
+
+
+
+
+/**
+ * @brief Initialize the HASH peripheral in SHA224 mode then initiate a DMA transfer
+ * to feed the input buffer to the Peripheral.
+ * @note Once the DMA transfer is finished, HAL_HASHEx_SHA224_Finish() API must
+ * be called to retrieve the computed digest.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief Return the computed digest in SHA224 mode.
+ * @note The API waits for DCIS to be set then reads the computed digest.
+ * @note HAL_HASHEx_SHA224_Finish() can be used as well to retrieve the digest in
+ * HMAC SHA224 mode.
+ * @param hhash HASH handle.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA224_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Finish(hhash, pOutBuffer, Timeout);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in SHA256 mode then initiate a DMA transfer
+ * to feed the input buffer to the Peripheral.
+ * @note Once the DMA transfer is finished, HAL_HASHEx_SHA256_Finish() API must
+ * be called to retrieve the computed digest.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @brief Return the computed digest in SHA256 mode.
+ * @note The API waits for DCIS to be set then reads the computed digest.
+ * @note HAL_HASHEx_SHA256_Finish() can be used as well to retrieve the digest in
+ * HMAC SHA256 mode.
+ * @param hhash HASH handle.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HASHEx_SHA256_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HASH_Finish(hhash, pOutBuffer, Timeout);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HASHEx_Exported_Functions_Group4 HMAC extended processing functions in polling mode
+ * @brief HMAC extended processing functions using polling mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### Polling mode HMAC extended processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in polling mode
+ the HMAC value using one of the following algorithms:
+ (+) SHA224
+ (++) HAL_HMACEx_SHA224_Start()
+ (+) SHA256
+ (++) HAL_HMACEx_SHA256_Start()
+
+@endverbatim
+ * @{
+ */
+
+
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC SHA224 mode, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC SHA256 mode, next process pInBuffer then
+ * read the computed digest.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes.
+ * @param Timeout Timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+ return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @}
+ */
+
+
+/** @defgroup HASHEx_Exported_Functions_Group5 HMAC extended processing functions in interrupt mode
+ * @brief HMAC extended processing functions using interruption mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### Interrupt mode HMAC extended processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in interrupt mode
+ the HMAC value using one of the following algorithms:
+ (+) SHA224
+ (++) HAL_HMACEx_SHA224_Start_IT()
+ (+) SHA256
+ (++) HAL_HMACEx_SHA256_Start_IT()
+
+@endverbatim
+ * @{
+ */
+
+
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC SHA224 mode, next process pInBuffer then
+ * read the computed digest in interrupt mode.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC SHA256 mode, next process pInBuffer then
+ * read the computed digest in interrupt mode.
+ * @note Digest is available in pOutBuffer.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
+{
+ return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA256);
+}
+
+
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup HASHEx_Exported_Functions_Group6 HMAC extended processing functions in DMA mode
+ * @brief HMAC extended processing functions using DMA mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### DMA mode HMAC extended processing functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to calculate in DMA mode
+ the HMAC value using one of the following algorithms:
+ (+) SHA224
+ (++) HAL_HMACEx_SHA224_Start_DMA()
+ (+) SHA256
+ (++) HAL_HMACEx_SHA256_Start_DMA()
+
+ [..] When resorting to DMA mode to enter the data in the Peripheral for HMAC processing,
+ user must resort to HAL_HMACEx_xxx_Start_DMA() then read the resulting digest
+ with HAL_HASHEx_xxx_Finish().
+
+
+@endverbatim
+ * @{
+ */
+
+
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC SHA224 mode then initiate the required
+ * DMA transfers to feed the key and the input buffer to the Peripheral.
+ * @note Once the DMA transfers are finished (indicated by hhash->State set back
+ * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA224_Finish() API must be called to retrieve
+ * the computed digest.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note If MDMAT bit is set before calling this function (multi-buffer
+ * HASH processing case), the input buffer size (in bytes) must be
+ * a multiple of 4 otherwise, the HASH digest computation is corrupted.
+ * For the processing of the last buffer of the thread, MDMAT bit must
+ * be reset and the buffer length (in bytes) doesn't have to be a
+ * multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief Initialize the HASH peripheral in HMAC SHA224 mode then initiate the required
+ * DMA transfers to feed the key and the input buffer to the Peripheral.
+ * @note Once the DMA transfers are finished (indicated by hhash->State set back
+ * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve
+ * the computed digest.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note If MDMAT bit is set before calling this function (multi-buffer
+ * HASH processing case), the input buffer size (in bytes) must be
+ * a multiple of 4 otherwise, the HASH digest computation is corrupted.
+ * For the processing of the last buffer of the thread, MDMAT bit must
+ * be reset and the buffer length (in bytes) doesn't have to be a
+ * multiple of 4.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (buffer to be hashed).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256);
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup HASHEx_Exported_Functions_Group7 Multi-buffer HMAC extended processing functions in DMA mode
+ * @brief HMAC extended processing functions in multi-buffer DMA mode.
+ *
+@verbatim
+ ===============================================================================
+ ##### Multi-buffer DMA mode HMAC extended processing functions #####
+ ===============================================================================
+ [..] This section provides functions to manage HMAC multi-buffer
+ DMA-based processing for MD5, SHA1, SHA224 and SHA256 algorithms.
+ (+) MD5
+ (++) HAL_HMACEx_MD5_Step1_2_DMA()
+ (++) HAL_HMACEx_MD5_Step2_DMA()
+ (++) HAL_HMACEx_MD5_Step2_3_DMA()
+ (+) SHA1
+ (++) HAL_HMACEx_SHA1_Step1_2_DMA()
+ (++) HAL_HMACEx_SHA1_Step2_DMA()
+ (++) HAL_HMACEx_SHA1_Step2_3_DMA()
+
+ (+) SHA256
+ (++) HAL_HMACEx_SHA224_Step1_2_DMA()
+ (++) HAL_HMACEx_SHA224_Step2_DMA()
+ (++) HAL_HMACEx_SHA224_Step2_3_DMA()
+ (+) SHA256
+ (++) HAL_HMACEx_SHA256_Step1_2_DMA()
+ (++) HAL_HMACEx_SHA256_Step2_DMA()
+ (++) HAL_HMACEx_SHA256_Step2_3_DMA()
+
+ [..] User must first start-up the multi-buffer DMA-based HMAC computation in
+ calling HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
+ intiates step 2 with the first input buffer.
+
+ [..] The following buffers are next fed to the Peripheral with a call to the API
+ HAL_HMACEx_xxx_Step2_DMA(). There may be several consecutive calls
+ to this API.
+
+ [..] Multi-buffer DMA-based HMAC computation is wrapped up by a call to
+ HAL_HMACEx_xxx_Step2_3_DMA(). This finishes step 2 in feeding the last input
+ buffer to the Peripheral then carries out step 3.
+
+ [..] Digest is retrieved by a call to HAL_HASH_xxx_Finish() for MD-5 or
+ SHA-1, to HAL_HASHEx_xxx_Finish() for SHA-224 or SHA-256.
+
+ [..] If only two buffers need to be consecutively processed, a call to
+ HAL_HMACEx_xxx_Step1_2_DMA() followed by a call to HAL_HMACEx_xxx_Step2_3_DMA()
+ is sufficient.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief MD5 HMAC step 1 completion and step 2 start in multi-buffer DMA mode.
+ * @note Step 1 consists in writing the inner hash function key in the Peripheral,
+ * step 2 consists in writing the message text.
+ * @note The API carries out the HMAC step 1 then starts step 2 with
+ * the first buffer entered to the Peripheral. DCAL bit is not automatically set after
+ * the message buffer feeding, allowing other messages DMA transfers to occur.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_MD5_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ hhash->DigestCalculationDisable = SET;
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief MD5 HMAC step 2 in multi-buffer DMA mode.
+ * @note Step 2 consists in writing the message text in the Peripheral.
+ * @note The API carries on the HMAC step 2, applied to the buffer entered as input
+ * parameter. DCAL bit is not automatically set after the message buffer feeding,
+ * allowing other messages DMA transfers to occur.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_MD5_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ if (hhash->DigestCalculationDisable != SET)
+ {
+ return HAL_ERROR;
+ }
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
+}
+
+/**
+ * @brief MD5 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode.
+ * @note Step 2 consists in writing the message text in the Peripheral,
+ * step 3 consists in writing the outer hash function key.
+ * @note The API wraps up the HMAC step 2 in processing the buffer entered as input
+ * parameter (the input buffer must be the last one of the multi-buffer thread)
+ * then carries out HMAC step 3.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note Once the DMA transfers are finished (indicated by hhash->State set back
+ * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve
+ * the computed digest.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_MD5_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ hhash->DigestCalculationDisable = RESET;
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
+}
+
+
+/**
+ * @brief SHA1 HMAC step 1 completion and step 2 start in multi-buffer DMA mode.
+ * @note Step 1 consists in writing the inner hash function key in the Peripheral,
+ * step 2 consists in writing the message text.
+ * @note The API carries out the HMAC step 1 then starts step 2 with
+ * the first buffer entered to the Peripheral. DCAL bit is not automatically set after
+ * the message buffer feeding, allowing other messages DMA transfers to occur.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA1_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ hhash->DigestCalculationDisable = SET;
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @brief SHA1 HMAC step 2 in multi-buffer DMA mode.
+ * @note Step 2 consists in writing the message text in the Peripheral.
+ * @note The API carries on the HMAC step 2, applied to the buffer entered as input
+ * parameter. DCAL bit is not automatically set after the message buffer feeding,
+ * allowing other messages DMA transfers to occur.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA1_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ if (hhash->DigestCalculationDisable != SET)
+ {
+ return HAL_ERROR;
+ }
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @brief SHA1 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode.
+ * @note Step 2 consists in writing the message text in the Peripheral,
+ * step 3 consists in writing the outer hash function key.
+ * @note The API wraps up the HMAC step 2 in processing the buffer entered as input
+ * parameter (the input buffer must be the last one of the multi-buffer thread)
+ * then carries out HMAC step 3.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note Once the DMA transfers are finished (indicated by hhash->State set back
+ * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve
+ * the computed digest.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA1_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ hhash->DigestCalculationDisable = RESET;
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
+}
+
+/**
+ * @brief SHA224 HMAC step 1 completion and step 2 start in multi-buffer DMA mode.
+ * @note Step 1 consists in writing the inner hash function key in the Peripheral,
+ * step 2 consists in writing the message text.
+ * @note The API carries out the HMAC step 1 then starts step 2 with
+ * the first buffer entered to the Peripheral. DCAL bit is not automatically set after
+ * the message buffer feeding, allowing other messages DMA transfers to occur.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA224_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ hhash->DigestCalculationDisable = SET;
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief SHA224 HMAC step 2 in multi-buffer DMA mode.
+ * @note Step 2 consists in writing the message text in the Peripheral.
+ * @note The API carries on the HMAC step 2, applied to the buffer entered as input
+ * parameter. DCAL bit is not automatically set after the message buffer feeding,
+ * allowing other messages DMA transfers to occur.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA224_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ if (hhash->DigestCalculationDisable != SET)
+ {
+ return HAL_ERROR;
+ }
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief SHA224 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode.
+ * @note Step 2 consists in writing the message text in the Peripheral,
+ * step 3 consists in writing the outer hash function key.
+ * @note The API wraps up the HMAC step 2 in processing the buffer entered as input
+ * parameter (the input buffer must be the last one of the multi-buffer thread)
+ * then carries out HMAC step 3.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note Once the DMA transfers are finished (indicated by hhash->State set back
+ * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve
+ * the computed digest.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA224_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ hhash->DigestCalculationDisable = RESET;
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224);
+}
+
+/**
+ * @brief SHA256 HMAC step 1 completion and step 2 start in multi-buffer DMA mode.
+ * @note Step 1 consists in writing the inner hash function key in the Peripheral,
+ * step 2 consists in writing the message text.
+ * @note The API carries out the HMAC step 1 then starts step 2 with
+ * the first buffer entered to the Peripheral. DCAL bit is not automatically set after
+ * the message buffer feeding, allowing other messages DMA transfers to occur.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA256_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ hhash->DigestCalculationDisable = SET;
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @brief SHA256 HMAC step 2 in multi-buffer DMA mode.
+ * @note Step 2 consists in writing the message text in the Peripheral.
+ * @note The API carries on the HMAC step 2, applied to the buffer entered as input
+ * parameter. DCAL bit is not automatically set after the message buffer feeding,
+ * allowing other messages DMA transfers to occur.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
+ * HASH digest computation is corrupted.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA256_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ if (hhash->DigestCalculationDisable != SET)
+ {
+ return HAL_ERROR;
+ }
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @brief SHA256 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode.
+ * @note Step 2 consists in writing the message text in the Peripheral,
+ * step 3 consists in writing the outer hash function key.
+ * @note The API wraps up the HMAC step 2 in processing the buffer entered as input
+ * parameter (the input buffer must be the last one of the multi-buffer thread)
+ * then carries out HMAC step 3.
+ * @note Same key is used for the inner and the outer hash functions; pointer to key and
+ * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
+ * @note Once the DMA transfers are finished (indicated by hhash->State set back
+ * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve
+ * the computed digest.
+ * @param hhash HASH handle.
+ * @param pInBuffer pointer to the input buffer (message buffer).
+ * @param Size length of the input buffer in bytes.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HMACEx_SHA256_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
+{
+ hhash->DigestCalculationDisable = RESET;
+ return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256);
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+#endif /* HAL_HASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+#endif /* HASH*/
+/**
+ * @}
+ */
+
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_hcd.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hcd.c
new file mode 100644
index 0000000000..974be7f9b0
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hcd.c
@@ -0,0 +1,1648 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_hcd.c
+ * @author MCD Application Team
+ * @brief HCD HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the USB Peripheral Controller:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#)Declare a HCD_HandleTypeDef handle structure, for example:
+ HCD_HandleTypeDef hhcd;
+
+ (#)Fill parameters of Init structure in HCD handle
+
+ (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
+
+ (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
+ (##) Enable the HCD/USB Low Level interface clock using the following macros
+ (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
+ (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
+ (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode)
+
+ (##) Initialize the related GPIO clocks
+ (##) Configure HCD pin-out
+ (##) Configure HCD NVIC interrupt
+
+ (#)Associate the Upper USB Host stack to the HAL HCD Driver:
+ (##) hhcd.pData = phost;
+
+ (#)Enable HCD transmission and reception:
+ (##) HAL_HCD_Start();
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_HCD_MODULE_ENABLED
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+
+/** @defgroup HCD HCD
+ * @brief HCD HAL module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup HCD_Private_Functions HCD Private Functions
+ * @{
+ */
+static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
+static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
+static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
+static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup HCD_Exported_Functions HCD Exported Functions
+ * @{
+ */
+
+/** @defgroup HCD_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 Initialize the host driver.
+ * @param hhcd HCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
+{
+ USB_OTG_GlobalTypeDef *USBx;
+
+ /* Check the HCD handle allocation */
+ if (hhcd == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
+
+ USBx = hhcd->Instance;
+
+ if (hhcd->State == HAL_HCD_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hhcd->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+ hhcd->SOFCallback = HAL_HCD_SOF_Callback;
+ hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
+ hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
+ hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
+ hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
+ hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
+
+ if (hhcd->MspInitCallback == NULL)
+ {
+ hhcd->MspInitCallback = HAL_HCD_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hhcd->MspInitCallback(hhcd);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ HAL_HCD_MspInit(hhcd);
+#endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
+ }
+
+ hhcd->State = HAL_HCD_STATE_BUSY;
+
+ /* Disable DMA mode for FS instance */
+ if ((USBx->CID & (0x1U << 8)) == 0U)
+ {
+ hhcd->Init.dma_enable = 0U;
+ }
+
+ /* Disable the Interrupts */
+ __HAL_HCD_DISABLE(hhcd);
+
+ /* Init the Core (common init.) */
+ (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
+
+ /* Force Host Mode*/
+ (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
+
+ /* Init Host */
+ (void)USB_HostInit(hhcd->Instance, hhcd->Init);
+
+ hhcd->State = HAL_HCD_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize a host channel.
+ * @param hhcd HCD handle
+ * @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:
+ * HCD_SPEED_HIGH: High speed mode,
+ * HCD_SPEED_FULL: Full speed mode,
+ * HCD_SPEED_LOW: Low speed mode
+ * @param ep_type Endpoint Type.
+ * This parameter can be one of these values:
+ * EP_TYPE_CTRL: Control type,
+ * EP_TYPE_ISOC: Isochronous type,
+ * EP_TYPE_BULK: Bulk type,
+ * EP_TYPE_INTR: Interrupt type
+ * @param mps Max Packet Size.
+ * This parameter can be a value from 0 to32K
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd,
+ uint8_t ch_num,
+ uint8_t epnum,
+ uint8_t dev_address,
+ uint8_t speed,
+ uint8_t ep_type,
+ uint16_t mps)
+{
+ HAL_StatusTypeDef status;
+
+ __HAL_LOCK(hhcd);
+ hhcd->hc[ch_num].do_ping = 0U;
+ hhcd->hc[ch_num].dev_addr = dev_address;
+ hhcd->hc[ch_num].max_packet = mps;
+ hhcd->hc[ch_num].ch_num = ch_num;
+ hhcd->hc[ch_num].ep_type = ep_type;
+ hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
+
+ if ((epnum & 0x80U) == 0x80U)
+ {
+ hhcd->hc[ch_num].ep_is_in = 1U;
+ }
+ else
+ {
+ hhcd->hc[ch_num].ep_is_in = 0U;
+ }
+
+ hhcd->hc[ch_num].speed = speed;
+
+ status = USB_HC_Init(hhcd->Instance,
+ ch_num,
+ epnum,
+ dev_address,
+ speed,
+ ep_type,
+ mps);
+ __HAL_UNLOCK(hhcd);
+
+ return status;
+}
+
+/**
+ * @brief Halt a host channel.
+ * @param hhcd HCD handle
+ * @param ch_num Channel number.
+ * This parameter can be a value from 1 to 15
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ __HAL_LOCK(hhcd);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_UNLOCK(hhcd);
+
+ return status;
+}
+
+/**
+ * @brief DeInitialize the host driver.
+ * @param hhcd HCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
+{
+ /* Check the HCD handle allocation */
+ if (hhcd == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ hhcd->State = HAL_HCD_STATE_BUSY;
+
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+ if (hhcd->MspDeInitCallback == NULL)
+ {
+ hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware */
+ hhcd->MspDeInitCallback(hhcd);
+#else
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ HAL_HCD_MspDeInit(hhcd);
+#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
+
+ __HAL_HCD_DISABLE(hhcd);
+
+ hhcd->State = HAL_HCD_STATE_RESET;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the HCD MSP.
+ * @param hhcd HCD handle
+ * @retval None
+ */
+__weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HCD_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the HCD MSP.
+ * @param hhcd HCD handle
+ * @retval None
+ */
+__weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HCD_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
+ * @brief HCD IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to manage the USB Host Data
+ Transfer
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Submit a new URB for processing.
+ * @param hhcd HCD handle
+ * @param ch_num Channel number.
+ * This parameter can be a value from 1 to 15
+ * @param direction Channel number.
+ * This parameter can be one of these values:
+ * 0 : Output / 1 : Input
+ * @param ep_type Endpoint Type.
+ * This parameter can be one of these values:
+ * EP_TYPE_CTRL: Control type/
+ * EP_TYPE_ISOC: Isochronous type/
+ * EP_TYPE_BULK: Bulk type/
+ * EP_TYPE_INTR: Interrupt type/
+ * @param token Endpoint Type.
+ * This parameter can be one of these values:
+ * 0: HC_PID_SETUP / 1: HC_PID_DATA1
+ * @param pbuff pointer to URB data
+ * @param length Length of URB data
+ * @param do_ping activate do ping protocol (for high speed only).
+ * This parameter can be one of these values:
+ * 0 : do ping inactive / 1 : do ping active
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
+ uint8_t ch_num,
+ uint8_t direction,
+ uint8_t ep_type,
+ uint8_t token,
+ uint8_t *pbuff,
+ uint16_t length,
+ uint8_t do_ping)
+{
+ hhcd->hc[ch_num].ep_is_in = direction;
+ hhcd->hc[ch_num].ep_type = ep_type;
+
+ if (token == 0U)
+ {
+ hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
+ hhcd->hc[ch_num].do_ping = do_ping;
+ }
+ else
+ {
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
+ }
+
+ /* Manage Data Toggle */
+ switch (ep_type)
+ {
+ case EP_TYPE_CTRL:
+ if ((token == 1U) && (direction == 0U)) /*send data */
+ {
+ if (length == 0U)
+ {
+ /* For Status OUT stage, Length==0, Status Out PID = 1 */
+ hhcd->hc[ch_num].toggle_out = 1U;
+ }
+
+ /* Set the Data Toggle bit as per the Flag */
+ if (hhcd->hc[ch_num].toggle_out == 0U)
+ {
+ /* Put the PID 0 */
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
+ }
+ else
+ {
+ /* Put the PID 1 */
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
+ }
+ }
+ break;
+
+ case EP_TYPE_BULK:
+ if (direction == 0U)
+ {
+ /* Set the Data Toggle bit as per the Flag */
+ if (hhcd->hc[ch_num].toggle_out == 0U)
+ {
+ /* Put the PID 0 */
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
+ }
+ else
+ {
+ /* Put the PID 1 */
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
+ }
+ }
+ else
+ {
+ if (hhcd->hc[ch_num].toggle_in == 0U)
+ {
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
+ }
+ else
+ {
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
+ }
+ }
+
+ break;
+ case EP_TYPE_INTR:
+ if (direction == 0U)
+ {
+ /* Set the Data Toggle bit as per the Flag */
+ if (hhcd->hc[ch_num].toggle_out == 0U)
+ {
+ /* Put the PID 0 */
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
+ }
+ else
+ {
+ /* Put the PID 1 */
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
+ }
+ }
+ else
+ {
+ if (hhcd->hc[ch_num].toggle_in == 0U)
+ {
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
+ }
+ else
+ {
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
+ }
+ }
+ break;
+
+ case EP_TYPE_ISOC:
+ hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
+ break;
+
+ default:
+ break;
+ }
+
+ hhcd->hc[ch_num].xfer_buff = pbuff;
+ hhcd->hc[ch_num].xfer_len = length;
+ hhcd->hc[ch_num].urb_state = URB_IDLE;
+ hhcd->hc[ch_num].xfer_count = 0U;
+ hhcd->hc[ch_num].ch_num = ch_num;
+ hhcd->hc[ch_num].state = HC_IDLE;
+
+ return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num], (uint8_t)hhcd->Init.dma_enable);
+}
+
+/**
+ * @brief Handle HCD interrupt request.
+ * @param hhcd HCD handle
+ * @retval None
+ */
+void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t i, interrupt;
+
+ /* Ensure that we are in device mode */
+ if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
+ {
+ /* Avoid spurious interrupt */
+ if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
+ {
+ return;
+ }
+
+ if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
+ {
+ /* Incorrect mode, acknowledge the interrupt */
+ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
+ }
+
+ if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
+ {
+ /* Incorrect mode, acknowledge the interrupt */
+ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
+ }
+
+ if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
+ {
+ /* Incorrect mode, acknowledge the interrupt */
+ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
+ }
+
+ if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
+ {
+ /* Incorrect mode, acknowledge the interrupt */
+ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
+ }
+
+ /* Handle Host Disconnect Interrupts */
+ if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
+ {
+ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
+
+ if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
+ {
+ /* Handle Host Port Disconnect Interrupt */
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+ hhcd->DisconnectCallback(hhcd);
+#else
+ HAL_HCD_Disconnect_Callback(hhcd);
+#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
+
+ (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
+ }
+ }
+
+ /* Handle Host Port Interrupts */
+ if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
+ {
+ HCD_Port_IRQHandler(hhcd);
+ }
+
+ /* Handle Host SOF Interrupt */
+ if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
+ {
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+ hhcd->SOFCallback(hhcd);
+#else
+ HAL_HCD_SOF_Callback(hhcd);
+#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
+
+ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
+ }
+
+ /* Handle Host channel Interrupt */
+ if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
+ {
+ interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
+ for (i = 0U; i < hhcd->Init.Host_channels; i++)
+ {
+ if ((interrupt & (1UL << (i & 0xFU))) != 0U)
+ {
+ if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
+ {
+ HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
+ }
+ else
+ {
+ HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
+ }
+ }
+ }
+ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
+ }
+
+ /* Handle Rx Queue Level Interrupts */
+ if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
+ {
+ USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+
+ HCD_RXQLVL_IRQHandler(hhcd);
+
+ USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+ }
+ }
+}
+
+/**
+ * @brief SOF callback.
+ * @param hhcd HCD handle
+ * @retval None
+ */
+__weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HCD_SOF_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Connection Event callback.
+ * @param hhcd HCD handle
+ * @retval None
+ */
+__weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HCD_Connect_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Disconnection Event callback.
+ * @param hhcd HCD handle
+ * @retval None
+ */
+__weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HCD_Disconnect_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Port Enabled Event callback.
+ * @param hhcd HCD handle
+ * @retval None
+ */
+__weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HCD_Disconnect_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Port Disabled Event callback.
+ * @param hhcd HCD handle
+ * @retval None
+ */
+__weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HCD_Disconnect_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Notify URB state change callback.
+ * @param hhcd HCD handle
+ * @param chnum Channel number.
+ * This parameter can be a value from 1 to 15
+ * @param urb_state:
+ * This parameter can be one of these values:
+ * URB_IDLE/
+ * URB_DONE/
+ * URB_NOTREADY/
+ * URB_NYET/
+ * URB_ERROR/
+ * URB_STALL/
+ * @retval None
+ */
+__weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhcd);
+ UNUSED(chnum);
+ UNUSED(urb_state);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+/**
+ * @brief Register a User USB HCD Callback
+ * To be used instead of the weak predefined callback
+ * @param hhcd USB HCD handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
+ * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
+ * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
+ * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
+ * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
+ * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
+ * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID, pHCD_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hhcd);
+
+ if (hhcd->State == HAL_HCD_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HCD_SOF_CB_ID :
+ hhcd->SOFCallback = pCallback;
+ break;
+
+ case HAL_HCD_CONNECT_CB_ID :
+ hhcd->ConnectCallback = pCallback;
+ break;
+
+ case HAL_HCD_DISCONNECT_CB_ID :
+ hhcd->DisconnectCallback = pCallback;
+ break;
+
+ case HAL_HCD_PORT_ENABLED_CB_ID :
+ hhcd->PortEnabledCallback = pCallback;
+ break;
+
+ case HAL_HCD_PORT_DISABLED_CB_ID :
+ hhcd->PortDisabledCallback = pCallback;
+ break;
+
+ case HAL_HCD_MSPINIT_CB_ID :
+ hhcd->MspInitCallback = pCallback;
+ break;
+
+ case HAL_HCD_MSPDEINIT_CB_ID :
+ hhcd->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hhcd->State == HAL_HCD_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HCD_MSPINIT_CB_ID :
+ hhcd->MspInitCallback = pCallback;
+ break;
+
+ case HAL_HCD_MSPDEINIT_CB_ID :
+ hhcd->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhcd);
+ return status;
+}
+
+/**
+ * @brief Unregister an USB HCD Callback
+ * USB HCD callabck is redirected to the weak predefined callback
+ * @param hhcd USB HCD handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
+ * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
+ * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
+ * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
+ * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
+ * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
+ * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hhcd);
+
+ /* Setup Legacy weak Callbacks */
+ if (hhcd->State == HAL_HCD_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HCD_SOF_CB_ID :
+ hhcd->SOFCallback = HAL_HCD_SOF_Callback;
+ break;
+
+ case HAL_HCD_CONNECT_CB_ID :
+ hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
+ break;
+
+ case HAL_HCD_DISCONNECT_CB_ID :
+ hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
+ break;
+
+ case HAL_HCD_PORT_ENABLED_CB_ID :
+ hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
+ break;
+
+ case HAL_HCD_PORT_DISABLED_CB_ID :
+ hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
+ break;
+
+ case HAL_HCD_MSPINIT_CB_ID :
+ hhcd->MspInitCallback = HAL_HCD_MspInit;
+ break;
+
+ case HAL_HCD_MSPDEINIT_CB_ID :
+ hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hhcd->State == HAL_HCD_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HCD_MSPINIT_CB_ID :
+ hhcd->MspInitCallback = HAL_HCD_MspInit;
+ break;
+
+ case HAL_HCD_MSPDEINIT_CB_ID :
+ hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhcd);
+ return status;
+}
+
+/**
+ * @brief Register USB HCD Host Channel Notify URB Change Callback
+ * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
+ * @param hhcd HCD handle
+ * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd, pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hhcd);
+
+ if (hhcd->State == HAL_HCD_STATE_READY)
+ {
+ hhcd->HC_NotifyURBChangeCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhcd);
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the USB HCD Host Channel Notify URB Change Callback
+ * USB HCD Host Channel Notify URB Change Callback is redirected to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
+ * @param hhcd HCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hhcd);
+
+ if (hhcd->State == HAL_HCD_STATE_READY)
+ {
+ hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhcd);
+
+ return status;
+}
+#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the HCD data
+ transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the host driver.
+ * @param hhcd HCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
+{
+ __HAL_LOCK(hhcd);
+ __HAL_HCD_ENABLE(hhcd);
+ (void)USB_DriveVbus(hhcd->Instance, 1U);
+ __HAL_UNLOCK(hhcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the host driver.
+ * @param hhcd HCD handle
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
+{
+ __HAL_LOCK(hhcd);
+ (void)USB_StopHost(hhcd->Instance);
+ __HAL_UNLOCK(hhcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reset the host port.
+ * @param hhcd HCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
+{
+ return (USB_ResetPort(hhcd->Instance));
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HCD_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 HCD handle state.
+ * @param hhcd HCD handle
+ * @retval HAL state
+ */
+HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
+{
+ return hhcd->State;
+}
+
+/**
+ * @brief Return URB state for a channel.
+ * @param hhcd HCD handle
+ * @param chnum Channel number.
+ * This parameter can be a value from 1 to 15
+ * @retval URB state.
+ * This parameter can be one of these values:
+ * URB_IDLE/
+ * URB_DONE/
+ * URB_NOTREADY/
+ * URB_NYET/
+ * URB_ERROR/
+ * URB_STALL
+ */
+HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
+{
+ return hhcd->hc[chnum].urb_state;
+}
+
+
+/**
+ * @brief Return the last host transfer size.
+ * @param hhcd HCD handle
+ * @param chnum Channel number.
+ * This parameter can be a value from 1 to 15
+ * @retval last transfer size in byte
+ */
+uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
+{
+ return hhcd->hc[chnum].xfer_count;
+}
+
+/**
+ * @brief Return the Host Channel state.
+ * @param hhcd HCD handle
+ * @param chnum Channel number.
+ * This parameter can be a value from 1 to 15
+ * @retval Host channel state
+ * This parameter can be one of these values:
+ * HC_IDLE/
+ * HC_XFRC/
+ * HC_HALTED/
+ * HC_NYET/
+ * HC_NAK/
+ * HC_STALL/
+ * HC_XACTERR/
+ * HC_BBLERR/
+ * HC_DATATGLERR
+ */
+HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
+{
+ return hhcd->hc[chnum].state;
+}
+
+/**
+ * @brief Return the current Host frame number.
+ * @param hhcd HCD handle
+ * @retval Current Host frame number
+ */
+uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
+{
+ return (USB_GetCurrentFrame(hhcd->Instance));
+}
+
+/**
+ * @brief Return the Host enumeration speed.
+ * @param hhcd HCD handle
+ * @retval Enumeration speed
+ */
+uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
+{
+ return (USB_GetHostSpeed(hhcd->Instance));
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup HCD_Private_Functions
+ * @{
+ */
+/**
+ * @brief Handle Host Channel IN interrupt requests.
+ * @param hhcd HCD handle
+ * @param chnum Channel number.
+ * This parameter can be a value from 1 to 15
+ * @retval none
+ */
+static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
+{
+ USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t ch_num = (uint32_t)chnum;
+
+ uint32_t tmpreg;
+
+ if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
+ {
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
+ {
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
+ {
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ hhcd->hc[ch_num].state = HC_STALL;
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
+ {
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
+ hhcd->hc[ch_num].state = HC_DATATGLERR;
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
+ }
+ else
+ {
+ /* ... */
+ }
+
+ if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
+ {
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
+ {
+ if (hhcd->Init.dma_enable != 0U)
+ {
+ hhcd->hc[ch_num].xfer_count = hhcd->hc[ch_num].xfer_len - \
+ (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
+ }
+
+ hhcd->hc[ch_num].state = HC_XFRC;
+ hhcd->hc[ch_num].ErrCnt = 0U;
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
+
+ if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
+ (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
+ {
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
+ }
+ else if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
+ {
+ USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
+ hhcd->hc[ch_num].urb_state = URB_DONE;
+
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+ hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
+#else
+ HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
+#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
+ }
+ else if (hhcd->hc[ch_num].ep_type == EP_TYPE_ISOC)
+ {
+ hhcd->hc[ch_num].urb_state = URB_DONE;
+
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+ hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
+#else
+ HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
+#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* ... */
+ }
+ hhcd->hc[ch_num].toggle_in ^= 1U;
+
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
+ {
+ __HAL_HCD_MASK_HALT_HC_INT(ch_num);
+
+ if (hhcd->hc[ch_num].state == HC_XFRC)
+ {
+ hhcd->hc[ch_num].urb_state = URB_DONE;
+ }
+ else if (hhcd->hc[ch_num].state == HC_STALL)
+ {
+ hhcd->hc[ch_num].urb_state = URB_STALL;
+ }
+ else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
+ (hhcd->hc[ch_num].state == HC_DATATGLERR))
+ {
+ hhcd->hc[ch_num].ErrCnt++;
+ if (hhcd->hc[ch_num].ErrCnt > 3U)
+ {
+ hhcd->hc[ch_num].ErrCnt = 0U;
+ hhcd->hc[ch_num].urb_state = URB_ERROR;
+ }
+ else
+ {
+ hhcd->hc[ch_num].urb_state = URB_NOTREADY;
+ }
+
+ /* re-activate the channel */
+ tmpreg = USBx_HC(ch_num)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(ch_num)->HCCHAR = tmpreg;
+ }
+ else if (hhcd->hc[ch_num].state == HC_NAK)
+ {
+ hhcd->hc[ch_num].urb_state = URB_NOTREADY;
+ /* re-activate the channel */
+ tmpreg = USBx_HC(ch_num)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(ch_num)->HCCHAR = tmpreg;
+ }
+ else
+ {
+ /* ... */
+ }
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
+ HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
+ {
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ hhcd->hc[ch_num].ErrCnt++;
+ hhcd->hc[ch_num].state = HC_XACTERR;
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
+ {
+ if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
+ {
+ hhcd->hc[ch_num].ErrCnt = 0U;
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ }
+ else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
+ (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
+ {
+ hhcd->hc[ch_num].ErrCnt = 0U;
+
+ if (hhcd->Init.dma_enable == 0U)
+ {
+ hhcd->hc[ch_num].state = HC_NAK;
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ }
+ }
+ else
+ {
+ /* ... */
+ }
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
+ }
+ else
+ {
+ /* ... */
+ }
+}
+
+/**
+ * @brief Handle Host Channel OUT interrupt requests.
+ * @param hhcd HCD handle
+ * @param chnum Channel number.
+ * This parameter can be a value from 1 to 15
+ * @retval none
+ */
+static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
+{
+ USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t ch_num = (uint32_t)chnum;
+ uint32_t tmpreg;
+
+ if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
+ {
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
+ {
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
+
+ if (hhcd->hc[ch_num].do_ping == 1U)
+ {
+ hhcd->hc[ch_num].do_ping = 0U;
+ hhcd->hc[ch_num].urb_state = URB_NOTREADY;
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ }
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET)
+ {
+ hhcd->hc[ch_num].state = HC_NYET;
+ hhcd->hc[ch_num].do_ping = 1U;
+ hhcd->hc[ch_num].ErrCnt = 0U;
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
+ {
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
+ {
+ hhcd->hc[ch_num].ErrCnt = 0U;
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
+ hhcd->hc[ch_num].state = HC_XFRC;
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
+ {
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ hhcd->hc[ch_num].state = HC_STALL;
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
+ {
+ hhcd->hc[ch_num].ErrCnt = 0U;
+ hhcd->hc[ch_num].state = HC_NAK;
+
+ if (hhcd->hc[ch_num].do_ping == 0U)
+ {
+ if (hhcd->hc[ch_num].speed == HCD_SPEED_HIGH)
+ {
+ hhcd->hc[ch_num].do_ping = 1U;
+ }
+ }
+
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
+ {
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ hhcd->hc[ch_num].state = HC_XACTERR;
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
+ {
+ __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
+ (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
+ hhcd->hc[ch_num].state = HC_DATATGLERR;
+ }
+ else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
+ {
+ __HAL_HCD_MASK_HALT_HC_INT(ch_num);
+
+ if (hhcd->hc[ch_num].state == HC_XFRC)
+ {
+ hhcd->hc[ch_num].urb_state = URB_DONE;
+ if ((hhcd->hc[ch_num].ep_type == EP_TYPE_BULK) ||
+ (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR))
+ {
+ hhcd->hc[ch_num].toggle_out ^= 1U;
+ }
+ }
+ else if (hhcd->hc[ch_num].state == HC_NAK)
+ {
+ hhcd->hc[ch_num].urb_state = URB_NOTREADY;
+ }
+ else if (hhcd->hc[ch_num].state == HC_NYET)
+ {
+ hhcd->hc[ch_num].urb_state = URB_NOTREADY;
+ }
+ else if (hhcd->hc[ch_num].state == HC_STALL)
+ {
+ hhcd->hc[ch_num].urb_state = URB_STALL;
+ }
+ else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
+ (hhcd->hc[ch_num].state == HC_DATATGLERR))
+ {
+ hhcd->hc[ch_num].ErrCnt++;
+ if (hhcd->hc[ch_num].ErrCnt > 3U)
+ {
+ hhcd->hc[ch_num].ErrCnt = 0U;
+ hhcd->hc[ch_num].urb_state = URB_ERROR;
+ }
+ else
+ {
+ hhcd->hc[ch_num].urb_state = URB_NOTREADY;
+ }
+
+ /* re-activate the channel */
+ tmpreg = USBx_HC(ch_num)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(ch_num)->HCCHAR = tmpreg;
+ }
+ else
+ {
+ /* ... */
+ }
+
+ __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
+ HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
+ }
+ else
+ {
+ /* ... */
+ }
+}
+
+/**
+ * @brief Handle Rx Queue Level interrupt requests.
+ * @param hhcd HCD handle
+ * @retval none
+ */
+static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t pktsts;
+ uint32_t pktcnt;
+ uint32_t temp;
+ uint32_t tmpreg;
+ uint32_t ch_num;
+
+ temp = hhcd->Instance->GRXSTSP;
+ ch_num = temp & USB_OTG_GRXSTSP_EPNUM;
+ pktsts = (temp & USB_OTG_GRXSTSP_PKTSTS) >> 17;
+ pktcnt = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
+
+ switch (pktsts)
+ {
+ case GRXSTS_PKTSTS_IN:
+ /* Read the data into the host buffer. */
+ if ((pktcnt > 0U) && (hhcd->hc[ch_num].xfer_buff != (void *)0))
+ {
+ (void)USB_ReadPacket(hhcd->Instance, hhcd->hc[ch_num].xfer_buff, (uint16_t)pktcnt);
+
+ /*manage multiple Xfer */
+ hhcd->hc[ch_num].xfer_buff += pktcnt;
+ hhcd->hc[ch_num].xfer_count += pktcnt;
+
+ if ((USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0U)
+ {
+ /* re-activate the channel when more packets are expected */
+ tmpreg = USBx_HC(ch_num)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(ch_num)->HCCHAR = tmpreg;
+ hhcd->hc[ch_num].toggle_in ^= 1U;
+ }
+ }
+ break;
+
+ case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
+ break;
+
+ case GRXSTS_PKTSTS_IN_XFER_COMP:
+ case GRXSTS_PKTSTS_CH_HALTED:
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief Handle Host Port interrupt requests.
+ * @param hhcd HCD handle
+ * @retval None
+ */
+static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ __IO uint32_t hprt0, hprt0_dup;
+
+ /* Handle Host Port Interrupts */
+ hprt0 = USBx_HPRT0;
+ hprt0_dup = USBx_HPRT0;
+
+ hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
+ USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
+
+ /* Check whether Port Connect detected */
+ if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
+ {
+ if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
+ {
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+ hhcd->ConnectCallback(hhcd);
+#else
+ HAL_HCD_Connect_Callback(hhcd);
+#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
+ }
+ hprt0_dup |= USB_OTG_HPRT_PCDET;
+ }
+
+ /* Check whether Port Enable Changed */
+ if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
+ {
+ hprt0_dup |= USB_OTG_HPRT_PENCHNG;
+
+ if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
+ {
+ if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
+ {
+ if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
+ {
+ (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
+ }
+ else
+ {
+ (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
+ }
+ }
+ else
+ {
+ if (hhcd->Init.speed == HCD_SPEED_FULL)
+ {
+ USBx_HOST->HFIR = 60000U;
+ }
+ }
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+ hhcd->PortEnabledCallback(hhcd);
+#else
+ HAL_HCD_PortEnabled_Callback(hhcd);
+#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
+
+ }
+ else
+ {
+#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
+ hhcd->PortDisabledCallback(hhcd);
+#else
+ HAL_HCD_PortDisabled_Callback(hhcd);
+#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Check for an overcurrent */
+ if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
+ {
+ hprt0_dup |= USB_OTG_HPRT_POCCHNG;
+ }
+
+ /* Clear Port Interrupts */
+ USBx_HPRT0 = hprt0_dup;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+#endif /* HAL_HCD_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_hrtim.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hrtim.c
new file mode 100644
index 0000000000..4f78ecf665
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hrtim.c
@@ -0,0 +1,9277 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_hrtim.c
+ * @author MCD Application Team
+ * @brief TIM HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the High Resolution Timer (HRTIM) peripheral:
+ * + HRTIM Initialization
+ * + Timer Time Base Unit Configuration
+ * + Simple Time Base Start/Stop
+ * + Simple Time Base Start/Stop Interrupt
+ * + Simple Time Base Start/Stop DMA Request
+ * + Simple Output Compare/PWM Channel Configuration
+ * + Simple Output Compare/PWM Channel Start/Stop Interrupt
+ * + Simple Output Compare/PWM Channel Start/Stop DMA Request
+ * + Simple Input Capture Channel Configuration
+ * + Simple Input Capture Channel Start/Stop Interrupt
+ * + Simple Input Capture Channel Start/Stop DMA Request
+ * + Simple One Pulse Channel Configuration
+ * + Simple One Pulse Channel Start/Stop Interrupt
+ * + HRTIM External Synchronization Configuration
+ * + HRTIM Burst Mode Controller Configuration
+ * + HRTIM Burst Mode Controller Enabling
+ * + HRTIM External Events Conditioning Configuration
+ * + HRTIM Faults Conditioning Configuration
+ * + HRTIM Faults Enabling
+ * + HRTIM ADC trigger Configuration
+ * + Waveform Timer Configuration
+ * + Waveform Event Filtering Configuration
+ * + Waveform Dead Time Insertion Configuration
+ * + Waveform Chopper Mode Configuration
+ * + Waveform Compare Unit Configuration
+ * + Waveform Capture Unit Configuration
+ * + Waveform Output Configuration
+ * + Waveform Counter Start/Stop
+ * + Waveform Counter Start/Stop Interrupt
+ * + Waveform Counter Start/Stop DMA Request
+ * + Waveform Output Enabling
+ * + Waveform Output Level Set/Get
+ * + Waveform Output State Get
+ * + Waveform Burst DMA Operation Configuration
+ * + Waveform Burst DMA Operation Start
+ * + Waveform Timer Counter Software Reset
+ * + Waveform Capture Software Trigger
+ * + Waveform Burst Mode Controller Software Trigger
+ * + Waveform Timer Pre-loadable Registers Update Enabling
+ * + Waveform Timer Pre-loadable Registers Software Update
+ * + Waveform Timer Delayed Protection Status Get
+ * + Waveform Timer Burst Status Get
+ * + Waveform Timer Push-Pull Status Get
+ * + Peripheral State Get
+ @verbatim
+==============================================================================
+ ##### Simple mode v.s. waveform mode #####
+==============================================================================
+ [..] The HRTIM HAL API is split into 2 categories:
+ (#)Simple functions: these functions allow for using a HRTIM timer as a
+ general purpose timer with high resolution capabilities.
+ HRTIM simple modes are managed through the set of functions named
+ HAL_HRTIM_Simple<Function>. These functions are similar in name and usage
+ to the one defined for the TIM peripheral. When a HRTIM timer operates in
+ simple mode, only a very limited set of HRTIM features are used.
+ Following simple modes are proposed:
+ (++)Output compare mode,
+ (++)PWM output mode,
+ (++)Input capture mode,
+ (++)One pulse mode.
+ (#)Waveform functions: These functions allow taking advantage of the HRTIM
+ flexibility to produce numerous types of control signal. When a HRTIM timer
+ operates in waveform mode, all the HRTIM features are accessible without
+ any restriction. HRTIM waveform modes are managed through the set of
+ functions named HAL_HRTIM_Waveform<Function>
+ ##### How to use this driver #####
+==============================================================================
+ [..]
+ (#)Initialize the HRTIM low level resources by implementing the
+ HAL_HRTIM_MspInit() function:
+ (##)Enable the HRTIM clock source using __HRTIMx_CLK_ENABLE()
+ (##)Connect HRTIM pins to MCU I/Os
+ (+++) Enable the clock for the HRTIM GPIOs using the following
+ function: __HAL_RCC_GPIOx_CLK_ENABLE()
+ (+++) Configure these GPIO pins in Alternate Function mode using
+ HAL_GPIO_Init()
+ (##)When using DMA to control data transfer (e.g HAL_HRTIM_SimpleBaseStart_DMA())
+ (+++)Enable the DMAx interface clock using __DMAx_CLK_ENABLE()
+ (+++)Initialize the DMA handle
+ (+++)Associate the initialized DMA handle to the appropriate DMA
+ handle of the HRTIM handle using __HAL_LINKDMA()
+ (+++)Initialize the DMA channel using HAL_DMA_Init()
+ (+++)Configure the priority and enable the NVIC for the transfer
+ complete interrupt on the DMA channel using HAL_NVIC_SetPriority()
+ and HAL_NVIC_EnableIRQ()
+ (##)In case of using interrupt mode (e.g HAL_HRTIM_SimpleBaseStart_IT())
+ (+++)Configure the priority and enable the NVIC for the concerned
+ HRTIM interrupt using HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ()
+
+ (#)Initialize the HRTIM HAL using HAL_HRTIM_Init(). The HRTIM configuration
+ structure (field of the HRTIM handle) specifies which global interrupt of
+ whole HRTIM must be enabled (Burst mode period, System fault, Faults).
+ It also contains the HRTIM external synchronization configuration. HRTIM
+ can act as a master (generating a synchronization signal) or as a slave
+ (waiting for a trigger to be synchronized).
+
+ (#) Configure HRTIM resources shared by all HRTIM timers
+ (##)Burst Mode Controller:
+ (+++)HAL_HRTIM_BurstModeConfig(): configures the HRTIM burst mode
+ controller: operating mode (continuous or one-shot mode), clock
+ (source, prescaler) , trigger(s), period, idle duration.
+ (##)External Events Conditioning:
+ (+++)HAL_HRTIM_EventConfig(): configures the conditioning of an
+ external event channel: source, polarity, edge-sensitivity.
+ External event can be used as triggers (timer reset, input
+ capture, burst mode, ADC triggers, delayed protection)
+ They can also be used to set or reset timer outputs. Up to
+ 10 event channels are available.
+ (+++)HAL_HRTIM_EventPrescalerConfig(): configures the external
+ event sampling clock (used for digital filtering).
+ (##)Fault Conditioning:
+ (+++)HAL_HRTIM_FaultConfig(): configures the conditioning of a
+ fault channel: source, polarity, edge-sensitivity. Fault
+ channels are used to disable the outputs in case of an
+ abnormal operation. Up to 5 fault channels are available.
+ (+++)HAL_HRTIM_FaultPrescalerConfig(): configures the fault
+ sampling clock (used for digital filtering).
+ (+++)HAL_HRTIM_FaultModeCtl(): Enables or disables fault input(s)
+ circuitry. By default all fault inputs are disabled.
+ (##)ADC trigger:
+ (+++)HAL_HRTIM_ADCTriggerConfig(): configures the source triggering
+ the update of the ADC trigger register and the ADC trigger.
+ 4 independent triggers are available to start both the regular
+ and the injected sequencers of the 2 ADCs
+
+ (#) Configure HRTIM timer time base using HAL_HRTIM_TimeBaseConfig(). This
+ function must be called whatever the HRTIM timer operating mode is
+ (simple v.s. waveform). It configures mainly:
+ (##)The HRTIM timer counter operating mode (continuous v.s. one shot)
+ (##)The HRTIM timer clock prescaler
+ (##)The HRTIM timer period
+ (##)The HRTIM timer repetition counter
+
+ *** If the HRTIM timer operates in simple mode ***
+ ===================================================
+ [..]
+ (#) Start or Stop simple timers
+ (++)Simple time base: HAL_HRTIM_SimpleBaseStart(),HAL_HRTIM_SimpleBaseStop(),
+ HAL_HRTIM_SimpleBaseStart_IT(),HAL_HRTIM_SimpleBaseStop_IT(),
+ HAL_HRTIM_SimpleBaseStart_DMA(),HAL_HRTIM_SimpleBaseStop_DMA().
+ (++)Simple output compare: HAL_HRTIM_SimpleOCChannelConfig(),
+ HAL_HRTIM_SimpleOCStart(),HAL_HRTIM_SimpleOCStop(),
+ HAL_HRTIM_SimpleOCStart_IT(),HAL_HRTIM_SimpleOCStop_IT(),
+ HAL_HRTIM_SimpleOCStart_DMA(),HAL_HRTIM_SimpleOCStop_DMA(),
+ (++)Simple PWM output: HAL_HRTIM_SimplePWMChannelConfig(),
+ HAL_HRTIM_SimplePWMStart(),HAL_HRTIM_SimplePWMStop(),
+ HAL_HRTIM_SimplePWMStart_IT(),HAL_HRTIM_SimplePWMStop_IT(),
+ HAL_HRTIM_SimplePWMStart_DMA(),HAL_HRTIM_SimplePWMStop_DMA(),
+ (++)Simple input capture: HAL_HRTIM_SimpleCaptureChannelConfig(),
+ HAL_HRTIM_SimpleCaptureStart(),HAL_HRTIM_SimpleCaptureStop(),
+ HAL_HRTIM_SimpleCaptureStart_IT(),HAL_HRTIM_SimpleCaptureStop_IT(),
+ HAL_HRTIM_SimpleCaptureStart_DMA(),HAL_HRTIM_SimpleCaptureStop_DMA().
+ (++)Simple one pulse: HAL_HRTIM_SimpleOnePulseChannelConfig(),
+ HAL_HRTIM_SimpleOnePulseStart(),HAL_HRTIM_SimpleOnePulseStop(),
+ HAL_HRTIM_SimpleOnePulseStart_IT(),HAL_HRTIM_SimpleOnePulseStop_It().
+
+ *** If the HRTIM timer operates in waveform mode ***
+ ====================================================
+ [..]
+ (#) Completes waveform timer configuration
+ (++)HAL_HRTIM_WaveformTimerConfig(): configuration of a HRTIM timer
+ operating in wave form mode mainly consists in:
+ (+++)Enabling the HRTIM timer interrupts and DMA requests.
+ (+++)Enabling the half mode for the HRTIM timer.
+ (+++)Defining how the HRTIM timer reacts to external synchronization input.
+ (+++)Enabling the push-pull mode for the HRTIM timer.
+ (+++)Enabling the fault channels for the HRTIM timer.
+ (+++)Enabling the dead-time insertion for the HRTIM timer.
+ (+++)Setting the delayed protection mode for the HRTIM timer (source and outputs
+ on which the delayed protection are applied).
+ (+++)Specifying the HRTIM timer update and reset triggers.
+ (+++)Specifying the HRTIM timer registers update policy (e.g. pre-load enabling).
+ (++)HAL_HRTIM_TimerEventFilteringConfig(): configures external
+ event blanking and windowing circuitry of a HRTIM timer:
+ (+++)Blanking: to mask external events during a defined time period a defined time period
+ (+++)Windowing, to enable external events only during a defined time period
+ (++)HAL_HRTIM_DeadTimeConfig(): configures the dead-time insertion
+ unit for a HRTIM timer. Allows to generate a couple of
+ complementary signals from a single reference waveform,
+ with programmable delays between active state.
+ (++)HAL_HRTIM_ChopperModeConfig(): configures the parameters of
+ the high-frequency carrier signal added on top of the timing
+ unit output. Chopper mode can be enabled or disabled for each
+ timer output separately (see HAL_HRTIM_WaveformOutputConfig()).
+ (++)HAL_HRTIM_BurstDMAConfig(): configures the burst DMA burst
+ controller. Allows having multiple HRTIM registers updated
+ with a single DMA request. The burst DMA operation is started
+ by calling HAL_HRTIM_BurstDMATransfer().
+ (++)HAL_HRTIM_WaveformCompareConfig():configures the compare unit
+ of a HRTIM timer. This operation consists in setting the
+ compare value and possibly specifying the auto delayed mode
+ for compare units 2 and 4 (allows to have compare events
+ generated relatively to capture events). Note that when auto
+ delayed mode is needed, the capture unit associated to the
+ compare unit must be configured separately.
+ (++)HAL_HRTIM_WaveformCaptureConfig(): configures the capture unit
+ of a HRTIM timer. This operation consists in specifying the
+ source(s) triggering the capture (timer register update event,
+ external event, timer output set/reset event, other HRTIM
+ timer related events).
+ (++)HAL_HRTIM_WaveformOutputConfig(): configuration of a HRTIM timer
+ output mainly consists in:
+ (+++)Setting the output polarity (active high or active low),
+ (+++)Defining the set/reset crossbar for the output,
+ (+++)Specifying the fault level (active or inactive) in IDLE and FAULT states.,
+
+ (#) Set waveform timer output(s) level
+ (++)HAL_HRTIM_WaveformSetOutputLevel(): forces the output to its
+ active or inactive level. For example, when deadtime insertion
+ is enabled it is necessary to force the output level by software
+ to have the outputs in a complementary state as soon as the RUN mode is entered.
+
+ (#) Enable or Disable waveform timer output(s)
+ (++)HAL_HRTIM_WaveformOutputStart(),HAL_HRTIM_WaveformOutputStop().
+
+ (#) Start or Stop waveform HRTIM timer(s).
+ (++)HAL_HRTIM_WaveformCountStart(),HAL_HRTIM_WaveformCountStop(),
+ (++)HAL_HRTIM_WaveformCountStart_IT(),HAL_HRTIM_WaveformCountStop_IT(),
+ (++)HAL_HRTIM_WaveformCountStart_DMA(),HAL_HRTIM_WaveformCountStop_DMA(),
+ (#) Burst mode controller enabling:
+ (++)HAL_HRTIM_BurstModeCtl(): activates or de-activates the
+ burst mode controller.
+
+ (#) Some HRTIM operations can be triggered by software:
+ (++)HAL_HRTIM_BurstModeSoftwareTrigger(): calling this function
+ trigs the burst operation.
+ (++)HAL_HRTIM_SoftwareCapture(): calling this function trigs the
+ capture of the HRTIM timer counter.
+ (++)HAL_HRTIM_SoftwareUpdate(): calling this function trigs the
+ update of the pre-loadable registers of the HRTIM timer
+ (++)HAL_HRTIM_SoftwareReset():calling this function resets the
+ HRTIM timer counter.
+
+ (#) Some functions can be used any time to retrieve HRTIM timer related
+ information
+ (++)HAL_HRTIM_GetCapturedValue(): returns actual value of the
+ capture register of the designated capture unit.
+ (++)HAL_HRTIM_WaveformGetOutputLevel(): returns actual level
+ (ACTIVE/INACTIVE) of the designated timer output.
+ (++)HAL_HRTIM_WaveformGetOutputState():returns actual state
+ (IDLE/RUN/FAULT) of the designated timer output.
+ (++)HAL_HRTIM_GetDelayedProtectionStatus():returns actual level
+ (ACTIVE/INACTIVE) of the designated output when the delayed
+ protection was triggered.
+ (++)HAL_HRTIM_GetBurstStatus(): returns the actual status
+ (ACTIVE/INACTIVE) of the burst mode controller.
+ (++)HAL_HRTIM_GetCurrentPushPullStatus(): when the push-pull mode
+ is enabled for the HRTIM timer (see HAL_HRTIM_WaveformTimerConfig()),
+ the push-pull status indicates on which output the signal is currently
+ active (e.g signal applied on output 1 and output 2 forced
+ inactive or vice versa).
+ (++)HAL_HRTIM_GetIdlePushPullStatus(): when the push-pull mode
+ is enabled for the HRTIM timer (see HAL_HRTIM_WaveformTimerConfig()),
+ the idle push-pull status indicates during which period the
+ delayed protection request occurred (e.g. protection occurred
+ when the output 1 was active and output 2 forced inactive or
+ vice versa).
+
+ (#) Some functions can be used any time to retrieve actual HRTIM status
+ (++)HAL_HRTIM_GetState(): returns actual HRTIM instance HAL state.
+
+ *** Callback registration ***
+ =============================
+ [..]
+ The compilation flag USE_HAL_HRTIM_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions HAL_HRTIM_RegisterCallback() or HAL_HRTIM_TIMxRegisterCallback()
+ to register an interrupt callback.
+
+ [..]
+ Function HAL_HRTIM_RegisterCallback() allows to register following callbacks:
+ (+) Fault1Callback : Fault 1 interrupt callback function
+ (+) Fault2Callback : Fault 2 interrupt callback function
+ (+) Fault3Callback : Fault 3 interrupt callback function
+ (+) Fault4Callback : Fault 4 interrupt callback function
+ (+) Fault5Callback : Fault 5 interrupt callback function
+ (+) SystemFaultCallback : System fault interrupt callback function
+ (+) BurstModePeriodCallback : Burst mode period interrupt callback function
+ (+) SynchronizationEventCallback : Sync Input interrupt callback function
+ (+) ErrorCallback : DMA error callback function
+ (+) MspInitCallback : HRTIM MspInit callback function
+ (+) MspDeInitCallback : HRTIM MspInit callback function
+
+ [..]
+ Function HAL_HRTIM_TIMxRegisterCallback() allows to register following callbacks:
+ (+) RegistersUpdateCallback : Timer x Update interrupt callback function
+ (+) RepetitionEventCallback : Timer x Repetition interrupt callback function
+ (+) Compare1EventCallback : Timer x Compare 1 match interrupt callback function
+ (+) Compare2EventCallback : Timer x Compare 2 match interrupt callback function
+ (+) Compare3EventCallback : Timer x Compare 3 match interrupt callback function
+ (+) Compare4EventCallback : Timer x Compare 4 match interrupt callback function
+ (+) Capture1EventCallback : Timer x Capture 1 interrupts callback function
+ (+) Capture2EventCallback : Timer x Capture 2 interrupts callback function
+ (+) DelayedProtectionCallback : Timer x Delayed protection interrupt callback function
+ (+) CounterResetCallback : Timer x counter reset/roll-over interrupt callback function
+ (+) Output1SetCallback : Timer x output 1 set interrupt callback function
+ (+) Output1ResetCallback : Timer x output 1 reset interrupt callback function
+ (+) Output2SetCallback : Timer x output 2 set interrupt callback function
+ (+) Output2ResetCallback : Timer x output 2 reset interrupt callback function
+ (+) BurstDMATransferCallback : Timer x Burst DMA completed interrupt callback function
+
+ [..]
+ Both functions take as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function HAL_HRTIM_UnRegisterCallback or HAL_HRTIM_TIMxUnRegisterCallback
+ to reset a callback to the default weak function. Both functions take as parameters
+ the HAL peripheral handle and the Callback ID.
+
+ [..]
+ By default, after the HAL_HRTIM_Init() and when the state is HAL_HRTIM_STATE_RESET
+ all callbacks are set to the corresponding weak functions (e.g HAL_HRTIM_Fault1Callback)
+ Exception done for MspInit and MspDeInit functions that are reset to the legacy
+ weak functions in the HAL_HRTIM_Init()/ HAL_HRTIM_DeInit() only when these
+ callbacks are null (not registered beforehand). If MspInit or MspDeInit are
+ not null, the HAL_HRTIM_Init()/ HAL_HRTIM_DeInit() keep and use the user
+ MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+
+ [..]
+ Callbacks can be registered/unregistered in HAL_HRTIM_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in HAL_HRTIM_STATE_READY or HAL_HRTIM_STATE_RESET states, 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_HRTIM_RegisterCallback() before calling HAL_HRTIM_DeInit()
+ or HAL_HRTIM_Init() function.
+
+ [..]
+ When the compilation flag USE_HAL_HRTIM_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
+
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_HRTIM_MODULE_ENABLED
+
+#if defined(HRTIM1)
+
+/** @defgroup HRTIM HRTIM
+ * @brief HRTIM HAL module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup HRTIM_Private_Defines HRTIM Private Define
+ * @{
+ */
+#define HRTIM_FLTR_FLTxEN (HRTIM_FLTR_FLT1EN |\
+ HRTIM_FLTR_FLT2EN |\
+ HRTIM_FLTR_FLT3EN |\
+ HRTIM_FLTR_FLT4EN | \
+ HRTIM_FLTR_FLT5EN)
+
+#define HRTIM_TIMCR_TIMUPDATETRIGGER (HRTIM_TIMUPDATETRIGGER_MASTER |\
+ HRTIM_TIMUPDATETRIGGER_TIMER_A |\
+ HRTIM_TIMUPDATETRIGGER_TIMER_B |\
+ HRTIM_TIMUPDATETRIGGER_TIMER_C |\
+ HRTIM_TIMUPDATETRIGGER_TIMER_D |\
+ HRTIM_TIMUPDATETRIGGER_TIMER_E)
+
+#define HRTIM_FLTINR1_FLTxLCK ((HRTIM_FAULTLOCK_READONLY) | \
+ (HRTIM_FAULTLOCK_READONLY << 8U) | \
+ (HRTIM_FAULTLOCK_READONLY << 16U) | \
+ (HRTIM_FAULTLOCK_READONLY << 24U))
+
+#define HRTIM_FLTINR2_FLTxLCK ((HRTIM_FAULTLOCK_READONLY) | \
+ (HRTIM_FAULTLOCK_READONLY << 8U))
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup HRTIM_Private_Variables HRTIM Private Variables
+ * @{
+ */
+static uint32_t TimerIdxToTimerId[] =
+{
+ HRTIM_TIMERID_TIMER_A,
+ HRTIM_TIMERID_TIMER_B,
+ HRTIM_TIMERID_TIMER_C,
+ HRTIM_TIMERID_TIMER_D,
+ HRTIM_TIMERID_TIMER_E,
+ HRTIM_TIMERID_MASTER,
+};
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup HRTIM_Private_Functions HRTIM Private Functions
+ * @{
+ */
+static void HRTIM_MasterBase_Config(HRTIM_HandleTypeDef * hhrtim,
+ HRTIM_TimeBaseCfgTypeDef * pTimeBaseCfg);
+
+static void HRTIM_TimingUnitBase_Config(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ HRTIM_TimeBaseCfgTypeDef * pTimeBaseCfg);
+
+static void HRTIM_MasterWaveform_Config(HRTIM_HandleTypeDef * hhrtim,
+ HRTIM_TimerCfgTypeDef * pTimerCfg);
+
+static void HRTIM_TimingUnitWaveform_Config(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ HRTIM_TimerCfgTypeDef * pTimerCfg);
+
+
+static void HRTIM_CaptureUnitConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureUnit,
+ uint32_t Event);
+
+static void HRTIM_OutputConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Output,
+ HRTIM_OutputCfgTypeDef * pOutputCfg);
+
+static void HRTIM_EventConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Event,
+ HRTIM_EventCfgTypeDef * pEventCfg);
+
+static void HRTIM_TIM_ResetConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Event);
+
+static uint32_t HRTIM_GetITFromOCMode(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel);
+
+static uint32_t HRTIM_GetDMAFromOCMode(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel);
+
+static DMA_HandleTypeDef * HRTIM_GetDMAHandleFromTimerIdx(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx);
+
+static uint32_t GetTimerIdxFromDMAHandle(HRTIM_HandleTypeDef * hhrtim,
+ DMA_HandleTypeDef * hdma);
+
+static void HRTIM_ForceRegistersUpdate(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx);
+
+static void HRTIM_HRTIM_ISR(HRTIM_HandleTypeDef * hhrtim);
+
+static void HRTIM_Master_ISR(HRTIM_HandleTypeDef * hhrtim);
+
+static void HRTIM_Timer_ISR(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx);
+
+static void HRTIM_DMAMasterCplt(DMA_HandleTypeDef *hdma);
+
+static void HRTIM_DMATimerxCplt(DMA_HandleTypeDef *hdma);
+
+static void HRTIM_DMAError(DMA_HandleTypeDef *hdma);
+
+static void HRTIM_BurstDMACplt(DMA_HandleTypeDef *hdma);
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+/** @defgroup HRTIM_Exported_Functions HRTIM Exported Functions
+ * @{
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+@verbatim
+ ===============================================================================
+ ##### Initialization and Time Base Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize a HRTIM instance
+ (+) De-initialize a HRTIM instance
+ (+) Initialize the HRTIM MSP
+ (+) De-initialize the HRTIM MSP
+ (+) Configure the time base unit of a HRTIM timer
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize a HRTIM instance
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_Init(HRTIM_HandleTypeDef * hhrtim)
+{
+ uint8_t timer_idx;
+ uint32_t hrtim_mcr;
+
+ /* Check the HRTIM handle allocation */
+ if(hhrtim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_ALL_INSTANCE(hhrtim->Instance));
+ assert_param(IS_HRTIM_IT(hhrtim->Init.HRTIMInterruptResquests));
+
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ if (hhrtim->State == HAL_HRTIM_STATE_RESET)
+ {
+ /* Initialize callback function pointers to their default values */
+ hhrtim->Fault1Callback = HAL_HRTIM_Fault1Callback;
+ hhrtim->Fault2Callback = HAL_HRTIM_Fault2Callback;
+ hhrtim->Fault3Callback = HAL_HRTIM_Fault3Callback;
+ hhrtim->Fault4Callback = HAL_HRTIM_Fault4Callback;
+ hhrtim->Fault5Callback = HAL_HRTIM_Fault5Callback;
+ hhrtim->SystemFaultCallback = HAL_HRTIM_SystemFaultCallback;
+ hhrtim->BurstModePeriodCallback = HAL_HRTIM_BurstModePeriodCallback;
+ hhrtim->SynchronizationEventCallback = HAL_HRTIM_SynchronizationEventCallback;
+ hhrtim->ErrorCallback = HAL_HRTIM_ErrorCallback;
+ hhrtim->RegistersUpdateCallback = HAL_HRTIM_RegistersUpdateCallback;
+ hhrtim->RepetitionEventCallback = HAL_HRTIM_RepetitionEventCallback;
+ hhrtim->Compare1EventCallback = HAL_HRTIM_Compare1EventCallback;
+ hhrtim->Compare2EventCallback = HAL_HRTIM_Compare2EventCallback;
+ hhrtim->Compare3EventCallback = HAL_HRTIM_Compare3EventCallback;
+ hhrtim->Compare4EventCallback = HAL_HRTIM_Compare4EventCallback;
+ hhrtim->Capture1EventCallback = HAL_HRTIM_Capture1EventCallback;
+ hhrtim->Capture2EventCallback = HAL_HRTIM_Capture2EventCallback;
+ hhrtim->DelayedProtectionCallback = HAL_HRTIM_DelayedProtectionCallback;
+ hhrtim->CounterResetCallback = HAL_HRTIM_CounterResetCallback;
+ hhrtim->Output1SetCallback = HAL_HRTIM_Output1SetCallback;
+ hhrtim->Output1ResetCallback = HAL_HRTIM_Output1ResetCallback;
+ hhrtim->Output2SetCallback = HAL_HRTIM_Output2SetCallback;
+ hhrtim->Output2ResetCallback = HAL_HRTIM_Output2ResetCallback;
+ hhrtim->BurstDMATransferCallback = HAL_HRTIM_BurstDMATransferCallback;
+
+ if (hhrtim->MspInitCallback == NULL)
+ {
+ hhrtim->MspInitCallback = HAL_HRTIM_MspInit;
+ }
+ }
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+
+ /* Set the HRTIM state */
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Initialize the DMA handles */
+ hhrtim->hdmaMaster = (DMA_HandleTypeDef *)NULL;
+ hhrtim->hdmaTimerA = (DMA_HandleTypeDef *)NULL;
+ hhrtim->hdmaTimerB = (DMA_HandleTypeDef *)NULL;
+ hhrtim->hdmaTimerC = (DMA_HandleTypeDef *)NULL;
+ hhrtim->hdmaTimerD = (DMA_HandleTypeDef *)NULL;
+ hhrtim->hdmaTimerE = (DMA_HandleTypeDef *)NULL;
+
+ /* HRTIM output synchronization configuration (if required) */
+ if ((hhrtim->Init.SyncOptions & HRTIM_SYNCOPTION_MASTER) != (uint32_t)RESET)
+ {
+ /* Check parameters */
+ assert_param(IS_HRTIM_SYNCOUTPUTSOURCE(hhrtim->Init.SyncOutputSource));
+ assert_param(IS_HRTIM_SYNCOUTPUTPOLARITY(hhrtim->Init.SyncOutputPolarity));
+
+ /* The synchronization output initialization procedure must be done prior
+ to the configuration of the MCU outputs (done within HAL_HRTIM_MspInit)
+ */
+ if (hhrtim->Instance == HRTIM1)
+ {
+ /* Enable the HRTIM peripheral clock */
+ __HAL_RCC_HRTIM1_CLK_ENABLE();
+ }
+
+ hrtim_mcr = hhrtim->Instance->sMasterRegs.MCR;
+
+ /* Set the event to be sent on the synchronization output */
+ hrtim_mcr &= ~(HRTIM_MCR_SYNC_SRC);
+ hrtim_mcr |= (hhrtim->Init.SyncOutputSource & HRTIM_MCR_SYNC_SRC);
+
+ /* Set the polarity of the synchronization output */
+ hrtim_mcr &= ~(HRTIM_MCR_SYNC_OUT);
+ hrtim_mcr |= (hhrtim->Init.SyncOutputPolarity & HRTIM_MCR_SYNC_OUT);
+
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sMasterRegs.MCR = hrtim_mcr;
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->MspInitCallback(hhrtim);
+#else
+ HAL_HRTIM_MspInit(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+
+ /* HRTIM input synchronization configuration (if required) */
+ if ((hhrtim->Init.SyncOptions & HRTIM_SYNCOPTION_SLAVE) != (uint32_t)RESET)
+ {
+ /* Check parameters */
+ assert_param(IS_HRTIM_SYNCINPUTSOURCE(hhrtim->Init.SyncInputSource));
+
+ hrtim_mcr = hhrtim->Instance->sMasterRegs.MCR;
+
+ /* Set the synchronization input source */
+ hrtim_mcr &= ~(HRTIM_MCR_SYNC_IN);
+ hrtim_mcr |= (hhrtim->Init.SyncInputSource & HRTIM_MCR_SYNC_IN);
+
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sMasterRegs.MCR = hrtim_mcr;
+ }
+
+ /* Initialize the HRTIM state*/
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Initialize the lock status of the HRTIM HAL API */
+ __HAL_UNLOCK(hhrtim);
+
+ /* Initialize timer related parameters */
+ for (timer_idx = HRTIM_TIMERINDEX_TIMER_A ;
+ timer_idx <= HRTIM_TIMERINDEX_MASTER ;
+ timer_idx++)
+ {
+ hhrtim->TimerParam[timer_idx].CaptureTrigger1 = HRTIM_CAPTURETRIGGER_NONE;
+ hhrtim->TimerParam[timer_idx].CaptureTrigger2 = HRTIM_CAPTURETRIGGER_NONE;
+ hhrtim->TimerParam[timer_idx].InterruptRequests = HRTIM_IT_NONE;
+ hhrtim->TimerParam[timer_idx].DMARequests = HRTIM_IT_NONE;
+ hhrtim->TimerParam[timer_idx].DMASrcAddress = 0U;
+ hhrtim->TimerParam[timer_idx].DMASize = 0U;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief De-initialize a HRTIM instance
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_DeInit (HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Check the HRTIM handle allocation */
+ if(hhrtim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_ALL_INSTANCE(hhrtim->Instance));
+
+ /* Set the HRTIM state */
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* DeInit the low level hardware */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ if (hhrtim->MspDeInitCallback == NULL)
+ {
+ hhrtim->MspDeInitCallback = HAL_HRTIM_MspDeInit;
+ }
+
+ hhrtim->MspDeInitCallback(hhrtim);
+#else
+ HAL_HRTIM_MspDeInit(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief MSP initialization for a HRTIM instance
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_MspInit(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief MSP de-initialization of a HRTIM instance
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_MspDeInit(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Configure the time base unit of a timer
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param pTimeBaseCfg pointer to the time base configuration structure
+ * @note This function must be called prior starting the timer
+ * @note The time-base unit initialization parameters specify:
+ * The timer counter operating mode (continuous, one shot),
+ * The timer clock prescaler,
+ * The timer period,
+ * The timer repetition counter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_TimeBaseConfig(HRTIM_HandleTypeDef *hhrtim,
+ uint32_t TimerIdx,
+ HRTIM_TimeBaseCfgTypeDef * pTimeBaseCfg)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+ assert_param(IS_HRTIM_PRESCALERRATIO(pTimeBaseCfg->PrescalerRatio));
+ assert_param(IS_HRTIM_MODE(pTimeBaseCfg->Mode));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Set the HRTIM state */
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ if (TimerIdx == HRTIM_TIMERINDEX_MASTER)
+ {
+ /* Configure master timer time base unit */
+ HRTIM_MasterBase_Config(hhrtim, pTimeBaseCfg);
+ }
+ else
+ {
+ /* Configure timing unit time base unit */
+ HRTIM_TimingUnitBase_Config(hhrtim, TimerIdx, pTimeBaseCfg);
+ }
+
+ /* Set HRTIM state */
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group2 Simple time base mode functions
+ * @brief Simple time base mode functions.
+@verbatim
+ ===============================================================================
+ ##### Simple time base mode functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start simple time base
+ (+) Stop simple time base
+ (+) Start simple time base and enable interrupt
+ (+) Stop simple time base and disable interrupt
+ (+) Start simple time base and enable DMA transfer
+ (+) Stop simple time base and disable DMA transfer
+ -@- When a HRTIM timer operates in simple time base mode, the timer
+ counter counts from 0 to the period value.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the counter of a timer operating in simple time base mode.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index.
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleBaseStart(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the counter of a timer operating in simple time base mode.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index.
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleBaseStop(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the counter of a timer operating in simple time base mode
+ * (Timer repetition interrupt is enabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index.
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleBaseStart_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable the repetition interrupt */
+ if (TimerIdx == HRTIM_TIMERINDEX_MASTER)
+ {
+ __HAL_HRTIM_MASTER_ENABLE_IT(hhrtim, HRTIM_MASTER_IT_MREP);
+ }
+ else
+ {
+ __HAL_HRTIM_TIMER_ENABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_REP);
+ }
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the counter of a timer operating in simple time base mode
+ * (Timer repetition interrupt is disabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index.
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleBaseStop_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the repetition interrupt */
+ if (TimerIdx == HRTIM_TIMERINDEX_MASTER)
+ {
+ __HAL_HRTIM_MASTER_DISABLE_IT(hhrtim, HRTIM_MASTER_IT_MREP);
+ }
+ else
+ {
+ __HAL_HRTIM_TIMER_DISABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_REP);
+ }
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the counter of a timer operating in simple time base mode
+ * (Timer repetition DMA request is enabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index.
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param SrcAddr DMA transfer source address
+ * @param DestAddr DMA transfer destination address
+ * @param Length The length of data items (data size) to be transferred
+ * from source to destination
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleBaseStart_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t SrcAddr,
+ uint32_t DestAddr,
+ uint32_t Length)
+{
+ DMA_HandleTypeDef * hdma;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ if(hhrtim->State == HAL_HRTIM_STATE_READY)
+ {
+ if((SrcAddr == 0U ) || (DestAddr == 0U ) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+ }
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ /* Get the timer DMA handler */
+ hdma = HRTIM_GetDMAHandleFromTimerIdx(hhrtim, TimerIdx);
+
+ if (hdma == NULL)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Set the DMA transfer completed callback */
+ if (TimerIdx == HRTIM_TIMERINDEX_MASTER)
+ {
+ hdma->XferCpltCallback = HRTIM_DMAMasterCplt;
+ }
+ else
+ {
+ hdma->XferCpltCallback = HRTIM_DMATimerxCplt;
+ }
+
+ /* Set the DMA error callback */
+ hdma->XferErrorCallback = HRTIM_DMAError ;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hdma, SrcAddr, DestAddr, Length) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer repetition DMA request */
+ if (TimerIdx == HRTIM_TIMERINDEX_MASTER)
+ {
+ __HAL_HRTIM_MASTER_ENABLE_DMA(hhrtim, HRTIM_MASTER_DMA_MREP);
+ }
+ else
+ {
+ __HAL_HRTIM_TIMER_ENABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_REP);
+ }
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the counter of a timer operating in simple time base mode
+ * (Timer repetition DMA request is disabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index.
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleBaseStop_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ DMA_HandleTypeDef * hdma;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ if (TimerIdx == HRTIM_TIMERINDEX_MASTER)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Disable the DMA */
+ if (HAL_DMA_Abort(hhrtim->hdmaMaster) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+ }
+ /* Disable the timer repetition DMA request */
+ __HAL_HRTIM_MASTER_DISABLE_DMA(hhrtim, HRTIM_MASTER_DMA_MREP);
+ }
+ else
+ {
+ /* Get the timer DMA handler */
+ hdma = HRTIM_GetDMAHandleFromTimerIdx(hhrtim, TimerIdx);
+
+ if (hdma == NULL)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+ }
+ else
+ {
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Disable the DMA */
+ if (HAL_DMA_Abort(hdma) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+ }
+
+ /* Disable the timer repetition DMA request */
+ __HAL_HRTIM_TIMER_DISABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_REP);
+ }
+ }
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ if (hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_OK;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group3 Simple output compare mode functions
+ * @brief Simple output compare functions
+@verbatim
+ ===============================================================================
+ ##### Simple output compare functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure simple output channel
+ (+) Start simple output compare
+ (+) Stop simple output compare
+ (+) Start simple output compare and enable interrupt
+ (+) Stop simple output compare and disable interrupt
+ (+) Start simple output compare and enable DMA transfer
+ (+) Stop simple output compare and disable DMA transfer
+ -@- When a HRTIM timer operates in simple output compare mode
+ the output level is set to a programmable value when a match
+ is found between the compare register and the counter.
+ Compare unit 1 is automatically associated to output 1
+ Compare unit 2 is automatically associated to output 2
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure an output in simple output compare mode
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OCChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @param pSimpleOCChannelCfg pointer to the simple output compare output configuration structure
+ * @note When the timer operates in simple output compare mode:
+ * Output 1 is implicitly controlled by the compare unit 1
+ * Output 2 is implicitly controlled by the compare unit 2
+ * Output Set/Reset crossbar is set according to the selected output compare mode:
+ * Toggle: SETxyR = RSTxyR = CMPy
+ * Active: SETxyR = CMPy, RSTxyR = 0
+ * Inactive: SETxy =0, RSTxy = CMPy
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOCChannelConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel,
+ HRTIM_SimpleOCChannelCfgTypeDef* pSimpleOCChannelCfg)
+{
+ uint32_t CompareUnit = (uint32_t)RESET;
+ HRTIM_OutputCfgTypeDef OutputCfg;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OCChannel));
+ assert_param(IS_HRTIM_BASICOCMODE(pSimpleOCChannelCfg->Mode));
+ assert_param(IS_HRTIM_OUTPUTPULSE(pSimpleOCChannelCfg->Pulse));
+ assert_param(IS_HRTIM_OUTPUTPOLARITY(pSimpleOCChannelCfg->Polarity));
+ assert_param(IS_HRTIM_OUTPUTIDLELEVEL(pSimpleOCChannelCfg->IdleLevel));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Set HRTIM state */
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure timer compare unit */
+ switch (OCChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ CompareUnit = HRTIM_COMPAREUNIT_1;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP1xR = pSimpleOCChannelCfg->Pulse;
+ break;
+ }
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ CompareUnit = HRTIM_COMPAREUNIT_2;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP2xR = pSimpleOCChannelCfg->Pulse;
+ break;
+ }
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Configure timer output */
+ OutputCfg.Polarity = (pSimpleOCChannelCfg->Polarity & HRTIM_OUTR_POL1);
+ OutputCfg.IdleLevel = (pSimpleOCChannelCfg->IdleLevel & HRTIM_OUTR_IDLES1);
+ OutputCfg.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_NONE;
+ OutputCfg.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;
+ OutputCfg.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLED;
+ OutputCfg.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;
+
+ switch (pSimpleOCChannelCfg->Mode)
+ {
+ case HRTIM_BASICOCMODE_TOGGLE:
+ {
+ if (CompareUnit == HRTIM_COMPAREUNIT_1)
+ {
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP1;
+ }
+ else
+ {
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP2;
+ }
+ OutputCfg.ResetSource = OutputCfg.SetSource;
+ break;
+ }
+
+ case HRTIM_BASICOCMODE_ACTIVE:
+ {
+ if (CompareUnit == HRTIM_COMPAREUNIT_1)
+ {
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP1;
+ }
+ else
+ {
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP2;
+ }
+ OutputCfg.ResetSource = HRTIM_OUTPUTRESET_NONE;
+ break;
+ }
+
+ case HRTIM_BASICOCMODE_INACTIVE:
+ {
+ if (CompareUnit == HRTIM_COMPAREUNIT_1)
+ {
+ OutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMCMP1;
+ }
+ else
+ {
+ OutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMCMP2;
+ }
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_NONE;
+ break;
+ }
+
+ default:
+ {
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_NONE;
+ OutputCfg.ResetSource = HRTIM_OUTPUTRESET_NONE;
+
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ HRTIM_OutputConfig(hhrtim,
+ TimerIdx,
+ OCChannel,
+ &OutputCfg);
+
+ /* Set HRTIM state */
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the output compare signal generation on the designed timer output
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OCChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOCStart(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OCChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable the timer output */
+ hhrtim->Instance->sCommonRegs.OENR |= OCChannel;
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the output compare signal generation on the designed timer output
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OCChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOCStop(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OCChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the timer output */
+ hhrtim->Instance->sCommonRegs.ODISR |= OCChannel;
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the output compare signal generation on the designed timer output
+ * (Interrupt is enabled (see note note below)).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OCChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @note Interrupt enabling depends on the chosen output compare mode
+ * Output toggle: compare match interrupt is enabled
+ * Output set active: output set interrupt is enabled
+ * Output set inactive: output reset interrupt is enabled
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOCStart_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel)
+{
+ uint32_t interrupt;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OCChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Get the interrupt to enable (depends on the output compare mode) */
+ interrupt = HRTIM_GetITFromOCMode(hhrtim, TimerIdx, OCChannel);
+
+ /* Enable the timer output */
+ hhrtim->Instance->sCommonRegs.OENR |= OCChannel;
+
+ /* Enable the timer interrupt (depends on the output compare mode) */
+ __HAL_HRTIM_TIMER_ENABLE_IT(hhrtim, TimerIdx, interrupt);
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the output compare signal generation on the designed timer output
+ * (Interrupt is disabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OCChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOCStop_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel)
+{
+ uint32_t interrupt;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OCChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the timer output */
+ hhrtim->Instance->sCommonRegs.ODISR |= OCChannel;
+
+ /* Get the interrupt to disable (depends on the output compare mode) */
+ interrupt = HRTIM_GetITFromOCMode(hhrtim, TimerIdx, OCChannel);
+
+ /* Disable the timer interrupt */
+ __HAL_HRTIM_TIMER_DISABLE_IT(hhrtim, TimerIdx, interrupt);
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the output compare signal generation on the designed timer output
+ * (DMA request is enabled (see note below)).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OCChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @param SrcAddr DMA transfer source address
+ * @param DestAddr DMA transfer destination address
+ * @param Length The length of data items (data size) to be transferred
+ * from source to destination
+ * @note DMA request enabling depends on the chosen output compare mode
+ * Output toggle: compare match DMA request is enabled
+ * Output set active: output set DMA request is enabled
+ * Output set inactive: output reset DMA request is enabled
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOCStart_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel,
+ uint32_t SrcAddr,
+ uint32_t DestAddr,
+ uint32_t Length)
+{
+ DMA_HandleTypeDef * hdma;
+ uint32_t dma_request;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OCChannel));
+
+ if((hhrtim->State == HAL_HRTIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ if((hhrtim->State == HAL_HRTIM_STATE_READY))
+ {
+ if((SrcAddr == 0U ) || (DestAddr == 0U ) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+ }
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ /* Enable the timer output */
+ hhrtim->Instance->sCommonRegs.OENR |= OCChannel;
+
+ /* Get the DMA request to enable */
+ dma_request = HRTIM_GetDMAFromOCMode(hhrtim, TimerIdx, OCChannel);
+
+ /* Get the timer DMA handler */
+ hdma = HRTIM_GetDMAHandleFromTimerIdx(hhrtim, TimerIdx);
+
+ if (hdma == NULL)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Set the DMA error callback */
+ hdma->XferErrorCallback = HRTIM_DMAError ;
+
+ /* Set the DMA transfer completed callback */
+ hdma->XferCpltCallback = HRTIM_DMATimerxCplt;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hdma, SrcAddr, DestAddr, Length) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer DMA request */
+ __HAL_HRTIM_TIMER_ENABLE_DMA(hhrtim, TimerIdx, dma_request);
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the output compare signal generation on the designed timer output
+ * (DMA request is disabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OCChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOCStop_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel)
+{
+ uint32_t dma_request;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OCChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the timer output */
+ hhrtim->Instance->sCommonRegs.ODISR |= OCChannel;
+
+ /* Get the timer DMA handler */
+ /* Disable the DMA */
+ if (HAL_DMA_Abort(HRTIM_GetDMAHandleFromTimerIdx(hhrtim, TimerIdx)) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Get the DMA request to disable */
+ dma_request = HRTIM_GetDMAFromOCMode(hhrtim, TimerIdx, OCChannel);
+
+ /* Disable the timer DMA request */
+ __HAL_HRTIM_TIMER_DISABLE_DMA(hhrtim, TimerIdx, dma_request);
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group4 Simple PWM output mode functions
+ * @brief Simple PWM output functions
+@verbatim
+ ===============================================================================
+ ##### Simple PWM output functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure simple PWM output channel
+ (+) Start simple PWM output
+ (+) Stop simple PWM output
+ (+) Start simple PWM output and enable interrupt
+ (+) Stop simple PWM output and disable interrupt
+ (+) Start simple PWM output and enable DMA transfer
+ (+) Stop simple PWM output and disable DMA transfer
+ -@- When a HRTIM timer operates in simple PWM output mode
+ the output level is set to a programmable value when a match is
+ found between the compare register and the counter and reset when
+ the timer period is reached. Duty cycle is determined by the
+ comparison value.
+ Compare unit 1 is automatically associated to output 1
+ Compare unit 2 is automatically associated to output 2
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure an output in simple PWM mode
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param PWMChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @param pSimplePWMChannelCfg pointer to the simple PWM output configuration structure
+ * @note When the timer operates in simple PWM output mode:
+ * Output 1 is implicitly controlled by the compare unit 1
+ * Output 2 is implicitly controlled by the compare unit 2
+ * Output Set/Reset crossbar is set as follows:
+ * Output 1: SETx1R = CMP1, RSTx1R = PER
+ * Output 2: SETx2R = CMP2, RST2R = PER
+ * @note When Simple PWM mode is used the registers preload mechanism is
+ * enabled (otherwise the behavior is not guaranteed).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimplePWMChannelConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t PWMChannel,
+ HRTIM_SimplePWMChannelCfgTypeDef* pSimplePWMChannelCfg)
+{
+ HRTIM_OutputCfgTypeDef OutputCfg;
+ uint32_t hrtim_timcr;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, PWMChannel));
+ assert_param(IS_HRTIM_OUTPUTPOLARITY(pSimplePWMChannelCfg->Polarity));
+ assert_param(IS_HRTIM_OUTPUTPULSE(pSimplePWMChannelCfg->Pulse));
+ assert_param(IS_HRTIM_OUTPUTIDLELEVEL(pSimplePWMChannelCfg->IdleLevel));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure timer compare unit */
+ switch (PWMChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP1xR = pSimplePWMChannelCfg->Pulse;
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP1;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP2xR = pSimplePWMChannelCfg->Pulse;
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP2;
+ break;
+ }
+ default:
+ {
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_NONE;
+ OutputCfg.ResetSource = HRTIM_OUTPUTRESET_NONE;
+
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Configure timer output */
+ OutputCfg.Polarity = (pSimplePWMChannelCfg->Polarity & HRTIM_OUTR_POL1);
+ OutputCfg.IdleLevel = (pSimplePWMChannelCfg->IdleLevel& HRTIM_OUTR_IDLES1);
+ OutputCfg.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_NONE;
+ OutputCfg.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;
+ OutputCfg.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLED;
+ OutputCfg.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;
+ OutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMPER;
+
+ HRTIM_OutputConfig(hhrtim,
+ TimerIdx,
+ PWMChannel,
+ &OutputCfg);
+
+ /* Enable the registers preload mechanism */
+ hrtim_timcr = hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR;
+ hrtim_timcr |= HRTIM_TIMCR_PREEN;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR = hrtim_timcr;
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the PWM output signal generation on the designed timer output
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param PWMChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimplePWMStart(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t PWMChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, PWMChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable the timer output */
+ hhrtim->Instance->sCommonRegs.OENR |= PWMChannel;
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the PWM output signal generation on the designed timer output
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param PWMChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimplePWMStop(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t PWMChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, PWMChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the timer output */
+ hhrtim->Instance->sCommonRegs.ODISR |= PWMChannel;
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the PWM output signal generation on the designed timer output
+ * (The compare interrupt is enabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param PWMChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimplePWMStart_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t PWMChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, PWMChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable the timer output */
+ hhrtim->Instance->sCommonRegs.OENR |= PWMChannel;
+
+ /* Enable the timer interrupt (depends on the PWM output) */
+ switch (PWMChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ __HAL_HRTIM_TIMER_ENABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP1);
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ __HAL_HRTIM_TIMER_ENABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the PWM output signal generation on the designed timer output
+ * (The compare interrupt is disabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param PWMChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimplePWMStop_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t PWMChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, PWMChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the timer output */
+ hhrtim->Instance->sCommonRegs.ODISR |= PWMChannel;
+
+ /* Disable the timer interrupt (depends on the PWM output) */
+ switch (PWMChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ __HAL_HRTIM_TIMER_DISABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP1);
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ __HAL_HRTIM_TIMER_DISABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the PWM output signal generation on the designed timer output
+ * (The compare DMA request is enabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param PWMChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @param SrcAddr DMA transfer source address
+ * @param DestAddr DMA transfer destination address
+ * @param Length The length of data items (data size) to be transferred
+ * from source to destination
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimplePWMStart_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t PWMChannel,
+ uint32_t SrcAddr,
+ uint32_t DestAddr,
+ uint32_t Length)
+{
+ DMA_HandleTypeDef * hdma;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, PWMChannel));
+
+ if((hhrtim->State == HAL_HRTIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ if((hhrtim->State == HAL_HRTIM_STATE_READY))
+ {
+ if((SrcAddr == 0U ) || (DestAddr == 0U ) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+ }
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ /* Enable the timer output */
+ hhrtim->Instance->sCommonRegs.OENR |= PWMChannel;
+
+ /* Get the timer DMA handler */
+ hdma = HRTIM_GetDMAHandleFromTimerIdx(hhrtim, TimerIdx);
+
+ if (hdma == NULL)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Set the DMA error callback */
+ hdma->XferErrorCallback = HRTIM_DMAError ;
+
+ /* Set the DMA transfer completed callback */
+ hdma->XferCpltCallback = HRTIM_DMATimerxCplt;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hdma, SrcAddr, DestAddr, Length) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer DMA request */
+ switch (PWMChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ __HAL_HRTIM_TIMER_ENABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_CMP1);
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ __HAL_HRTIM_TIMER_ENABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_CMP2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the PWM output signal generation on the designed timer output
+ * (The compare DMA request is disabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param PWMChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimplePWMStop_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t PWMChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, PWMChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the timer output */
+ hhrtim->Instance->sCommonRegs.ODISR |= PWMChannel;
+
+ /* Get the timer DMA handler */
+ /* Disable the DMA */
+ if (HAL_DMA_Abort(HRTIM_GetDMAHandleFromTimerIdx(hhrtim, TimerIdx)) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Disable the timer DMA request */
+ switch (PWMChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ __HAL_HRTIM_TIMER_DISABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_CMP1);
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ __HAL_HRTIM_TIMER_DISABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_CMP2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group5 Simple input capture functions
+ * @brief Simple input capture functions
+@verbatim
+ ===============================================================================
+ ##### Simple input capture functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure simple input capture channel
+ (+) Start simple input capture
+ (+) Stop simple input capture
+ (+) Start simple input capture and enable interrupt
+ (+) Stop simple input capture and disable interrupt
+ (+) Start simple input capture and enable DMA transfer
+ (+) Stop simple input capture and disable DMA transfer
+ -@- When a HRTIM timer operates in simple input capture mode
+ the Capture Register (HRTIM_CPT1/2xR) is used to latch the
+ value of the timer counter counter after a transition detected
+ on a given external event input.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure a simple capture
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureChannel Capture unit
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @param pSimpleCaptureChannelCfg pointer to the simple capture configuration structure
+ * @note When the timer operates in simple capture mode the capture is trigerred
+ * by the designated external event and GPIO input is implicitly used as event source.
+ * The cature can be triggered by a rising edge, a falling edge or both
+ * edges on event channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleCaptureChannelConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureChannel,
+ HRTIM_SimpleCaptureChannelCfgTypeDef* pSimpleCaptureChannelCfg)
+{
+ HRTIM_EventCfgTypeDef EventCfg;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CAPTUREUNIT(CaptureChannel));
+ assert_param(IS_HRTIM_EVENT(pSimpleCaptureChannelCfg->Event));
+ assert_param(IS_HRTIM_EVENTPOLARITY(pSimpleCaptureChannelCfg->EventSensitivity,
+ pSimpleCaptureChannelCfg->EventPolarity));
+ assert_param(IS_HRTIM_EVENTSENSITIVITY(pSimpleCaptureChannelCfg->EventSensitivity));
+ assert_param(IS_HRTIM_EVENTFILTER(pSimpleCaptureChannelCfg->Event,
+ pSimpleCaptureChannelCfg->EventFilter));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure external event channel */
+ EventCfg.FastMode = HRTIM_EVENTFASTMODE_DISABLE;
+ EventCfg.Filter = (pSimpleCaptureChannelCfg->EventFilter & HRTIM_EECR3_EE6F);
+ EventCfg.Polarity = (pSimpleCaptureChannelCfg->EventPolarity & HRTIM_EECR1_EE1POL);
+ EventCfg.Sensitivity = (pSimpleCaptureChannelCfg->EventSensitivity & HRTIM_EECR1_EE1SNS);
+ EventCfg.Source = HRTIM_EVENTSRC_1;
+
+ HRTIM_EventConfig(hhrtim,
+ pSimpleCaptureChannelCfg->Event,
+ &EventCfg);
+
+ /* Memorize capture trigger (will be configured when the capture is started */
+ HRTIM_CaptureUnitConfig(hhrtim,
+ TimerIdx,
+ CaptureChannel,
+ pSimpleCaptureChannelCfg->Event);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable a simple capture on the designed capture unit
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @retval HAL status
+ * @note The external event triggering the capture is available for all timing
+ * units. It can be used directly and is active as soon as the timing
+ * unit counter is enabled.
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleCaptureStart(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CAPTUREUNIT(CaptureChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set the capture unit trigger */
+ switch (CaptureChannel)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR = hhrtim->TimerParam[TimerIdx].CaptureTrigger1;
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR = hhrtim->TimerParam[TimerIdx].CaptureTrigger2;
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable a simple capture on the designed capture unit
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleCaptureStop(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureChannel)
+{
+ uint32_t hrtim_cpt1cr;
+ uint32_t hrtim_cpt2cr;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CAPTUREUNIT(CaptureChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set the capture unit trigger */
+ switch (CaptureChannel)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR = HRTIM_CAPTURETRIGGER_NONE;
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR = HRTIM_CAPTURETRIGGER_NONE;
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ hrtim_cpt1cr = hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR;
+ hrtim_cpt2cr = hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR;
+
+ /* Disable the timer counter */
+ if ((hrtim_cpt1cr == HRTIM_CAPTURETRIGGER_NONE) &&
+ (hrtim_cpt2cr == HRTIM_CAPTURETRIGGER_NONE))
+ {
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+ }
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable a simple capture on the designed capture unit
+ * (Capture interrupt is enabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleCaptureStart_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CAPTUREUNIT(CaptureChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set the capture unit trigger */
+ switch (CaptureChannel)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR = hhrtim->TimerParam[TimerIdx].CaptureTrigger1;
+
+ /* Enable the capture unit 1 interrupt */
+ __HAL_HRTIM_TIMER_ENABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CPT1);
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR = hhrtim->TimerParam[TimerIdx].CaptureTrigger2;
+
+ /* Enable the capture unit 2 interrupt */
+ __HAL_HRTIM_TIMER_ENABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CPT2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable a simple capture on the designed capture unit
+ * (Capture interrupt is disabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleCaptureStop_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureChannel)
+{
+
+ uint32_t hrtim_cpt1cr;
+ uint32_t hrtim_cpt2cr;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CAPTUREUNIT(CaptureChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set the capture unit trigger */
+ switch (CaptureChannel)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR = HRTIM_CAPTURETRIGGER_NONE;
+
+ /* Disable the capture unit 1 interrupt */
+ __HAL_HRTIM_TIMER_DISABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CPT1);
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR = HRTIM_CAPTURETRIGGER_NONE;
+
+ /* Disable the capture unit 2 interrupt */
+ __HAL_HRTIM_TIMER_DISABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CPT2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ hrtim_cpt1cr = hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR;
+ hrtim_cpt2cr = hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR;
+
+ /* Disable the timer counter */
+ if ((hrtim_cpt1cr == HRTIM_CAPTURETRIGGER_NONE) &&
+ (hrtim_cpt2cr == HRTIM_CAPTURETRIGGER_NONE))
+ {
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+ }
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable a simple capture on the designed capture unit
+ * (Capture DMA request is enabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @param SrcAddr DMA transfer source address
+ * @param DestAddr DMA transfer destination address
+ * @param Length The length of data items (data size) to be transferred
+ * from source to destination
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleCaptureStart_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureChannel,
+ uint32_t SrcAddr,
+ uint32_t DestAddr,
+ uint32_t Length)
+{
+ DMA_HandleTypeDef * hdma;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CAPTUREUNIT(CaptureChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Get the timer DMA handler */
+ hdma = HRTIM_GetDMAHandleFromTimerIdx(hhrtim, TimerIdx);
+
+ if (hdma == NULL)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Set the DMA error callback */
+ hdma->XferErrorCallback = HRTIM_DMAError ;
+
+ /* Set the DMA transfer completed callback */
+ hdma->XferCpltCallback = HRTIM_DMATimerxCplt;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hdma, SrcAddr, DestAddr, Length) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ switch (CaptureChannel)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ /* Set the capture unit trigger */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR = hhrtim->TimerParam[TimerIdx].CaptureTrigger1;
+
+ __HAL_HRTIM_TIMER_ENABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_CPT1);
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ /* Set the capture unit trigger */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR = hhrtim->TimerParam[TimerIdx].CaptureTrigger2;
+
+ /* Enable the timer DMA request */
+ __HAL_HRTIM_TIMER_ENABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_CPT2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable a simple capture on the designed capture unit
+ * (Capture DMA request is disabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleCaptureStop_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureChannel)
+{
+
+ uint32_t hrtim_cpt1cr;
+ uint32_t hrtim_cpt2cr;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CAPTUREUNIT(CaptureChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Get the timer DMA handler */
+ /* Disable the DMA */
+ if (HAL_DMA_Abort(HRTIM_GetDMAHandleFromTimerIdx(hhrtim, TimerIdx)) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ switch (CaptureChannel)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ /* Reset the capture unit trigger */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR = HRTIM_CAPTURETRIGGER_NONE;
+
+ /* Disable the capture unit 1 DMA request */
+ __HAL_HRTIM_TIMER_DISABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_CPT1);
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ /* Reset the capture unit trigger */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR = HRTIM_CAPTURETRIGGER_NONE;
+
+ /* Disable the capture unit 2 DMA request */
+ __HAL_HRTIM_TIMER_DISABLE_DMA(hhrtim, TimerIdx, HRTIM_TIM_DMA_CPT2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ hrtim_cpt1cr = hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR;
+ hrtim_cpt2cr = hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR;
+
+ /* Disable the timer counter */
+ if ((hrtim_cpt1cr == HRTIM_CAPTURETRIGGER_NONE) &&
+ (hrtim_cpt2cr == HRTIM_CAPTURETRIGGER_NONE))
+ {
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+ }
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group6 Simple one pulse functions
+ * @brief Simple one pulse functions
+@verbatim
+ ===============================================================================
+ ##### Simple one pulse functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure one pulse channel
+ (+) Start one pulse generation
+ (+) Stop one pulse generation
+ (+) Start one pulse generation and enable interrupt
+ (+) Stop one pulse generation and disable interrupt
+ -@- When a HRTIM timer operates in simple one pulse mode
+ the timer counter is started in response to transition detected
+ on a given external event input to generate a pulse with a
+ programmable length after a programmable delay.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure an output simple one pulse mode
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OnePulseChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @param pSimpleOnePulseChannelCfg pointer to the simple one pulse output configuration structure
+ * @note When the timer operates in simple one pulse mode:
+ * the timer counter is implicitly started by the reset event,
+ * the reset of the timer counter is triggered by the designated external event
+ * GPIO input is implicitly used as event source,
+ * Output 1 is implicitly controlled by the compare unit 1,
+ * Output 2 is implicitly controlled by the compare unit 2.
+ * Output Set/Reset crossbar is set as follows:
+ * Output 1: SETx1R = CMP1, RSTx1R = PER
+ * Output 2: SETx2R = CMP2, RST2R = PER
+ * @retval HAL status
+ * @note If HAL_HRTIM_SimpleOnePulseChannelConfig is called for both timer
+ * outputs, the reset event related configuration data provided in the
+ * second call will override the reset event related configuration data
+ * provided in the first call.
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOnePulseChannelConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OnePulseChannel,
+ HRTIM_SimpleOnePulseChannelCfgTypeDef* pSimpleOnePulseChannelCfg)
+{
+ HRTIM_OutputCfgTypeDef OutputCfg;
+ HRTIM_EventCfgTypeDef EventCfg;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OnePulseChannel));
+ assert_param(IS_HRTIM_OUTPUTPULSE(pSimpleOnePulseChannelCfg->Pulse));
+ assert_param(IS_HRTIM_OUTPUTPOLARITY(pSimpleOnePulseChannelCfg->OutputPolarity));
+ assert_param(IS_HRTIM_OUTPUTIDLELEVEL(pSimpleOnePulseChannelCfg->OutputIdleLevel));
+ assert_param(IS_HRTIM_EVENT(pSimpleOnePulseChannelCfg->Event));
+ assert_param(IS_HRTIM_EVENTPOLARITY(pSimpleOnePulseChannelCfg->EventSensitivity,
+ pSimpleOnePulseChannelCfg->EventPolarity));
+ assert_param(IS_HRTIM_EVENTSENSITIVITY(pSimpleOnePulseChannelCfg->EventSensitivity));
+ assert_param(IS_HRTIM_EVENTFILTER(pSimpleOnePulseChannelCfg->Event,
+ pSimpleOnePulseChannelCfg->EventFilter));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure timer compare unit */
+ switch (OnePulseChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP1xR = pSimpleOnePulseChannelCfg->Pulse;
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP1;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP2xR = pSimpleOnePulseChannelCfg->Pulse;
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP2;
+ break;
+ }
+
+ default:
+ {
+ OutputCfg.SetSource = HRTIM_OUTPUTSET_NONE;
+ OutputCfg.ResetSource = HRTIM_OUTPUTRESET_NONE;
+
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Configure timer output */
+ OutputCfg.Polarity = (pSimpleOnePulseChannelCfg->OutputPolarity & HRTIM_OUTR_POL1);
+ OutputCfg.IdleLevel = (pSimpleOnePulseChannelCfg->OutputIdleLevel & HRTIM_OUTR_IDLES1);
+ OutputCfg.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_NONE;
+ OutputCfg.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;
+ OutputCfg.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLED;
+ OutputCfg.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;
+ OutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMPER;
+
+ HRTIM_OutputConfig(hhrtim,
+ TimerIdx,
+ OnePulseChannel,
+ &OutputCfg);
+
+ /* Configure external event channel */
+ EventCfg.FastMode = HRTIM_EVENTFASTMODE_DISABLE;
+ EventCfg.Filter = (pSimpleOnePulseChannelCfg->EventFilter & HRTIM_EECR3_EE6F);
+ EventCfg.Polarity = (pSimpleOnePulseChannelCfg->EventPolarity & HRTIM_OUTR_POL1);
+ EventCfg.Sensitivity = (pSimpleOnePulseChannelCfg->EventSensitivity &HRTIM_EECR1_EE1SNS);
+ EventCfg.Source = HRTIM_EVENTSRC_1;
+
+ HRTIM_EventConfig(hhrtim,
+ pSimpleOnePulseChannelCfg->Event,
+ &EventCfg);
+
+ /* Configure the timer reset register */
+ HRTIM_TIM_ResetConfig(hhrtim,
+ TimerIdx,
+ pSimpleOnePulseChannelCfg->Event);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the simple one pulse signal generation on the designed output
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OnePulseChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOnePulseStart(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OnePulseChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OnePulseChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable the timer output */
+ hhrtim->Instance->sCommonRegs.OENR |= OnePulseChannel;
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the simple one pulse signal generation on the designed output
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OnePulseChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOnePulseStop(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OnePulseChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OnePulseChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the timer output */
+ hhrtim->Instance->sCommonRegs.ODISR |= OnePulseChannel;
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the simple one pulse signal generation on the designed output
+ * (The compare interrupt is enabled (pulse start)).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OnePulseChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOnePulseStart_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OnePulseChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OnePulseChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable the timer output */
+ hhrtim->Instance->sCommonRegs.OENR |= OnePulseChannel;
+
+ /* Enable the timer interrupt (depends on the OnePulse output) */
+ switch (OnePulseChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ __HAL_HRTIM_TIMER_ENABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP1);
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ __HAL_HRTIM_TIMER_ENABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the simple one pulse signal generation on the designed output
+ * (The compare interrupt is disabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param OnePulseChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_SimpleOnePulseStop_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OnePulseChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, OnePulseChannel));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable the timer output */
+ hhrtim->Instance->sCommonRegs.ODISR |= OnePulseChannel;
+
+ /* Disable the timer interrupt (depends on the OnePulse output) */
+ switch (OnePulseChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ __HAL_HRTIM_TIMER_DISABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP1);
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ __HAL_HRTIM_TIMER_DISABLE_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP2);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, TimerIdxToTimerId[TimerIdx]);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group7 Configuration functions
+ * @brief HRTIM configuration functions
+@verbatim
+ ===============================================================================
+ ##### HRTIM configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to configure the HRTIM
+ resources shared by all the HRTIM timers operating in waveform mode:
+ (+) Configure the burst mode controller
+ (+) Configure an external event conditioning
+ (+) Configure the external events sampling clock
+ (+) Configure a fault conditioning
+ (+) Enable or disable fault inputs
+ (+) Configure the faults sampling clock
+ (+) Configure an ADC trigger
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the burst mode feature of the HRTIM
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param pBurstModeCfg pointer to the burst mode configuration structure
+ * @retval HAL status
+ * @note This function must be called before starting the burst mode
+ * controller
+ */
+HAL_StatusTypeDef HAL_HRTIM_BurstModeConfig(HRTIM_HandleTypeDef * hhrtim,
+ HRTIM_BurstModeCfgTypeDef* pBurstModeCfg)
+{
+ uint32_t hrtim_bmcr;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_BURSTMODE(pBurstModeCfg->Mode));
+ assert_param(IS_HRTIM_BURSTMODECLOCKSOURCE(pBurstModeCfg->ClockSource));
+ assert_param(IS_HRTIM_HRTIM_BURSTMODEPRESCALER(pBurstModeCfg->Prescaler));
+ assert_param(IS_HRTIM_BURSTMODEPRELOAD(pBurstModeCfg->PreloadEnable));
+ assert_param(IS_HRTIM_BURSTMODETRIGGER(pBurstModeCfg->Trigger));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ hrtim_bmcr = hhrtim->Instance->sCommonRegs.BMCR;
+
+ /* Set the burst mode operating mode */
+ hrtim_bmcr &= ~(HRTIM_BMCR_BMOM);
+ hrtim_bmcr |= (pBurstModeCfg->Mode & HRTIM_BMCR_BMOM);
+
+ /* Set the burst mode clock source */
+ hrtim_bmcr &= ~(HRTIM_BMCR_BMCLK);
+ hrtim_bmcr |= (pBurstModeCfg->ClockSource & HRTIM_BMCR_BMCLK);
+
+ /* Set the burst mode prescaler */
+ hrtim_bmcr &= ~(HRTIM_BMCR_BMPRSC);
+ hrtim_bmcr |= pBurstModeCfg->Prescaler;
+
+ /* Enable/disable burst mode registers preload */
+ hrtim_bmcr &= ~(HRTIM_BMCR_BMPREN);
+ hrtim_bmcr |= (pBurstModeCfg->PreloadEnable & HRTIM_BMCR_BMPREN);
+
+ /* Set the burst mode trigger */
+ hhrtim->Instance->sCommonRegs.BMTRGR = pBurstModeCfg->Trigger;
+
+ /* Set the burst mode compare value */
+ hhrtim->Instance->sCommonRegs.BMCMPR = pBurstModeCfg->IdleDuration;
+
+ /* Set the burst mode period */
+ hhrtim->Instance->sCommonRegs.BMPER = pBurstModeCfg->Period;
+
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sCommonRegs.BMCR = hrtim_bmcr;
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the conditioning of an external event
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Event external event to configure
+ * This parameter can be one of the following values:
+ * @arg HRTIM_EVENT_NONE: no external Event
+ * @arg HRTIM_EVENT_1: External event 1
+ * @arg HRTIM_EVENT_2: External event 2
+ * @arg HRTIM_EVENT_3: External event 3
+ * @arg HRTIM_EVENT_4: External event 4
+ * @arg HRTIM_EVENT_5: External event 5
+ * @arg HRTIM_EVENT_6: External event 6
+ * @arg HRTIM_EVENT_7: External event 7
+ * @arg HRTIM_EVENT_8: External event 8
+ * @arg HRTIM_EVENT_9: External event 9
+ * @arg HRTIM_EVENT_10: External event 10
+ * @param pEventCfg pointer to the event conditioning configuration structure
+ * @note This function must be called before starting the timer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_EventConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Event,
+ HRTIM_EventCfgTypeDef* pEventCfg)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_EVENT(Event));
+ assert_param(IS_HRTIM_EVENTSRC(pEventCfg->Source));
+ assert_param(IS_HRTIM_EVENTPOLARITY(pEventCfg->Sensitivity, pEventCfg->Polarity));
+ assert_param(IS_HRTIM_EVENTSENSITIVITY(pEventCfg->Sensitivity));
+ assert_param(IS_HRTIM_EVENTFASTMODE(Event, pEventCfg->FastMode));
+ assert_param(IS_HRTIM_EVENTFILTER(Event, pEventCfg->Filter));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure the event channel */
+ HRTIM_EventConfig(hhrtim, Event, pEventCfg);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the external event conditioning block prescaler
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Prescaler Prescaler value
+ * This parameter can be one of the following values:
+ * @arg HRTIM_EVENTPRESCALER_DIV1: fEEVS=fHRTIM
+ * @arg HRTIM_EVENTPRESCALER_DIV2: fEEVS=fHRTIM / 2
+ * @arg HRTIM_EVENTPRESCALER_DIV4: fEEVS=fHRTIM / 4
+ * @arg HRTIM_EVENTPRESCALER_DIV8: fEEVS=fHRTIM / 8
+ * @note This function must be called before starting the timer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_EventPrescalerConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Prescaler)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_EVENTPRESCALER(Prescaler));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set the external event prescaler */
+ MODIFY_REG(hhrtim->Instance->sCommonRegs.EECR3, HRTIM_EECR3_EEVSD, (Prescaler & HRTIM_EECR3_EEVSD));
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the conditioning of fault input
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Fault fault input to configure
+ * This parameter can be one of the following values:
+ * @arg HRTIM_FAULT_1: Fault input 1
+ * @arg HRTIM_FAULT_2: Fault input 2
+ * @arg HRTIM_FAULT_3: Fault input 3
+ * @arg HRTIM_FAULT_4: Fault input 4
+ * @arg HRTIM_FAULT_5: Fault input 5
+ * @param pFaultCfg pointer to the fault conditioning configuration structure
+ * @note This function must be called before starting the timer and before
+ * enabling faults inputs
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_FaultConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Fault,
+ HRTIM_FaultCfgTypeDef* pFaultCfg)
+{
+ uint32_t hrtim_fltinr1;
+ uint32_t hrtim_fltinr2;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_FAULT(Fault));
+ assert_param(IS_HRTIM_FAULTSOURCE(pFaultCfg->Source));
+ assert_param(IS_HRTIM_FAULTPOLARITY(pFaultCfg->Polarity));
+ assert_param(IS_HRTIM_FAULTFILTER(pFaultCfg->Filter));
+ assert_param(IS_HRTIM_FAULTLOCK(pFaultCfg->Lock));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure fault channel */
+ hrtim_fltinr1 = hhrtim->Instance->sCommonRegs.FLTINR1;
+ hrtim_fltinr2 = hhrtim->Instance->sCommonRegs.FLTINR2;
+
+ switch (Fault)
+ {
+ case HRTIM_FAULT_1:
+ {
+ hrtim_fltinr1 &= ~(HRTIM_FLTINR1_FLT1P | HRTIM_FLTINR1_FLT1SRC | HRTIM_FLTINR1_FLT1F | HRTIM_FLTINR1_FLT1LCK);
+ hrtim_fltinr1 |= (pFaultCfg->Polarity & HRTIM_FLTINR1_FLT1P);
+ hrtim_fltinr1 |= (pFaultCfg->Source & HRTIM_FLTINR1_FLT1SRC);
+ hrtim_fltinr1 |= (pFaultCfg->Filter & HRTIM_FLTINR1_FLT1F);
+ hrtim_fltinr1 |= (pFaultCfg->Lock & HRTIM_FLTINR1_FLT1LCK);
+ break;
+ }
+
+ case HRTIM_FAULT_2:
+ {
+ hrtim_fltinr1 &= ~(HRTIM_FLTINR1_FLT2P | HRTIM_FLTINR1_FLT2SRC | HRTIM_FLTINR1_FLT2F | HRTIM_FLTINR1_FLT2LCK);
+ hrtim_fltinr1 |= ((pFaultCfg->Polarity << 8U) & HRTIM_FLTINR1_FLT2P);
+ hrtim_fltinr1 |= ((pFaultCfg->Source << 8U) & HRTIM_FLTINR1_FLT2SRC);
+ hrtim_fltinr1 |= ((pFaultCfg->Filter << 8U) & HRTIM_FLTINR1_FLT2F);
+ hrtim_fltinr1 |= ((pFaultCfg->Lock << 8U) & HRTIM_FLTINR1_FLT2LCK);
+ break;
+ }
+
+ case HRTIM_FAULT_3:
+ {
+ hrtim_fltinr1 &= ~(HRTIM_FLTINR1_FLT3P | HRTIM_FLTINR1_FLT3SRC | HRTIM_FLTINR1_FLT3F | HRTIM_FLTINR1_FLT3LCK);
+ hrtim_fltinr1 |= ((pFaultCfg->Polarity << 16U) & HRTIM_FLTINR1_FLT3P);
+ hrtim_fltinr1 |= ((pFaultCfg->Source << 16U) & HRTIM_FLTINR1_FLT3SRC);
+ hrtim_fltinr1 |= ((pFaultCfg->Filter << 16U) & HRTIM_FLTINR1_FLT3F);
+ hrtim_fltinr1 |= ((pFaultCfg->Lock << 16U) & HRTIM_FLTINR1_FLT3LCK);
+ break;
+ }
+
+ case HRTIM_FAULT_4:
+ {
+ hrtim_fltinr1 &= ~(HRTIM_FLTINR1_FLT4P | HRTIM_FLTINR1_FLT4SRC | HRTIM_FLTINR1_FLT4F | HRTIM_FLTINR1_FLT4LCK);
+ hrtim_fltinr1 |= ((pFaultCfg->Polarity << 24U) & HRTIM_FLTINR1_FLT4P);
+ hrtim_fltinr1 |= ((pFaultCfg->Source << 24U) & HRTIM_FLTINR1_FLT4SRC);
+ hrtim_fltinr1 |= ((pFaultCfg->Filter << 24U) & HRTIM_FLTINR1_FLT4F);
+ hrtim_fltinr1 |= ((pFaultCfg->Lock << 24U) & HRTIM_FLTINR1_FLT4LCK);
+ break;
+ }
+
+ case HRTIM_FAULT_5:
+ {
+ hrtim_fltinr2 &= ~(HRTIM_FLTINR2_FLT5P | HRTIM_FLTINR2_FLT5SRC | HRTIM_FLTINR2_FLT5F | HRTIM_FLTINR2_FLT5LCK);
+ hrtim_fltinr2 |= (pFaultCfg->Polarity & HRTIM_FLTINR2_FLT5P);
+ hrtim_fltinr2 |= (pFaultCfg->Source & HRTIM_FLTINR2_FLT5SRC);
+ hrtim_fltinr2 |= (pFaultCfg->Filter & HRTIM_FLTINR2_FLT5F);
+ hrtim_fltinr2 |= (pFaultCfg->Lock & HRTIM_FLTINR2_FLT5LCK);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Update the HRTIM registers except LOCK bit */
+ hhrtim->Instance->sCommonRegs.FLTINR1 = (hrtim_fltinr1 & (~(HRTIM_FLTINR1_FLTxLCK)));
+ hhrtim->Instance->sCommonRegs.FLTINR2 = (hrtim_fltinr2 & (~(HRTIM_FLTINR2_FLTxLCK)));
+
+ /* Update the HRTIM registers LOCK bit */
+ SET_BIT(hhrtim->Instance->sCommonRegs.FLTINR1,(hrtim_fltinr1 & HRTIM_FLTINR1_FLTxLCK));
+ SET_BIT(hhrtim->Instance->sCommonRegs.FLTINR2,(hrtim_fltinr2 & HRTIM_FLTINR2_FLTxLCK));
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the fault conditioning block prescaler
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Prescaler Prescaler value
+ * This parameter can be one of the following values:
+ * @arg HRTIM_FAULTPRESCALER_DIV1: fFLTS=fHRTIM
+ * @arg HRTIM_FAULTPRESCALER_DIV2: fFLTS=fHRTIM / 2
+ * @arg HRTIM_FAULTPRESCALER_DIV4: fFLTS=fHRTIM / 4
+ * @arg HRTIM_FAULTPRESCALER_DIV8: fFLTS=fHRTIM / 8
+ * @retval HAL status
+ * @note This function must be called before starting the timer and before
+ * enabling faults inputs
+ */
+HAL_StatusTypeDef HAL_HRTIM_FaultPrescalerConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Prescaler)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_FAULTPRESCALER(Prescaler));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set the external event prescaler */
+ MODIFY_REG(hhrtim->Instance->sCommonRegs.FLTINR2, HRTIM_FLTINR2_FLTSD, (Prescaler & HRTIM_FLTINR2_FLTSD));
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable or disables the HRTIMx Fault mode.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Faults fault input(s) to enable or disable
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_FAULT_1: Fault input 1
+ * @arg HRTIM_FAULT_2: Fault input 2
+ * @arg HRTIM_FAULT_3: Fault input 3
+ * @arg HRTIM_FAULT_4: Fault input 4
+ * @arg HRTIM_FAULT_5: Fault input 5
+ * @param Enable Fault(s) enabling
+ * This parameter can be one of the following values:
+ * @arg HRTIM_FAULTMODECTL_ENABLED: Fault(s) enabled
+ * @arg HRTIM_FAULTMODECTL_DISABLED: Fault(s) disabled
+ * @retval None
+ */
+void HAL_HRTIM_FaultModeCtl(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Faults,
+ uint32_t Enable)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_FAULT(Faults));
+ assert_param(IS_HRTIM_FAULTMODECTL(Enable));
+
+ if ((Faults & HRTIM_FAULT_1) != (uint32_t)RESET)
+ {
+ MODIFY_REG(hhrtim->Instance->sCommonRegs.FLTINR1, HRTIM_FLTINR1_FLT1E, (Enable & HRTIM_FLTINR1_FLT1E));
+ }
+ if ((Faults & HRTIM_FAULT_2) != (uint32_t)RESET)
+ {
+ MODIFY_REG(hhrtim->Instance->sCommonRegs.FLTINR1, HRTIM_FLTINR1_FLT2E, ((Enable << 8U) & HRTIM_FLTINR1_FLT2E));
+ }
+ if ((Faults & HRTIM_FAULT_3) != (uint32_t)RESET)
+ {
+ MODIFY_REG(hhrtim->Instance->sCommonRegs.FLTINR1, HRTIM_FLTINR1_FLT3E, ((Enable << 16U) & HRTIM_FLTINR1_FLT3E));
+ }
+ if ((Faults & HRTIM_FAULT_4) != (uint32_t)RESET)
+ {
+ MODIFY_REG(hhrtim->Instance->sCommonRegs.FLTINR1, HRTIM_FLTINR1_FLT4E, ((Enable << 24U) & HRTIM_FLTINR1_FLT4E));
+ }
+ if ((Faults & HRTIM_FAULT_5) != (uint32_t)RESET)
+ {
+ MODIFY_REG(hhrtim->Instance->sCommonRegs.FLTINR2, HRTIM_FLTINR2_FLT5E, ((Enable) & HRTIM_FLTINR2_FLT5E));
+ }
+}
+
+/**
+ * @brief Configure both the ADC trigger register update source and the ADC
+ * trigger source.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param ADCTrigger ADC trigger to configure
+ * This parameter can be one of the following values:
+ * @arg HRTIM_ADCTRIGGER_1: ADC trigger 1
+ * @arg HRTIM_ADCTRIGGER_2: ADC trigger 2
+ * @arg HRTIM_ADCTRIGGER_3: ADC trigger 3
+ * @arg HRTIM_ADCTRIGGER_4: ADC trigger 4
+ * @param pADCTriggerCfg pointer to the ADC trigger configuration structure
+ * @retval HAL status
+ * @note This function must be called before starting the timer
+ */
+HAL_StatusTypeDef HAL_HRTIM_ADCTriggerConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t ADCTrigger,
+ HRTIM_ADCTriggerCfgTypeDef* pADCTriggerCfg)
+{
+ uint32_t hrtim_cr1;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_ADCTRIGGER(ADCTrigger));
+ assert_param(IS_HRTIM_ADCTRIGGERUPDATE(pADCTriggerCfg->UpdateSource));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set the ADC trigger update source */
+ hrtim_cr1 = hhrtim->Instance->sCommonRegs.CR1;
+
+ switch (ADCTrigger)
+ {
+ case HRTIM_ADCTRIGGER_1:
+ {
+ hrtim_cr1 &= ~(HRTIM_CR1_ADC1USRC);
+ hrtim_cr1 |= (pADCTriggerCfg->UpdateSource & HRTIM_CR1_ADC1USRC);
+
+ /* Set the ADC trigger 1 source */
+ hhrtim->Instance->sCommonRegs.ADC1R = pADCTriggerCfg->Trigger;
+ break;
+ }
+
+ case HRTIM_ADCTRIGGER_2:
+ {
+ hrtim_cr1 &= ~(HRTIM_CR1_ADC2USRC);
+ hrtim_cr1 |= ((pADCTriggerCfg->UpdateSource << 3U) & HRTIM_CR1_ADC2USRC);
+
+ /* Set the ADC trigger 2 source */
+ hhrtim->Instance->sCommonRegs.ADC2R = pADCTriggerCfg->Trigger;
+ break;
+ }
+
+ case HRTIM_ADCTRIGGER_3:
+ {
+ hrtim_cr1 &= ~(HRTIM_CR1_ADC3USRC);
+ hrtim_cr1 |= ((pADCTriggerCfg->UpdateSource << 6U) & HRTIM_CR1_ADC3USRC);
+
+ /* Set the ADC trigger 3 source */
+ hhrtim->Instance->sCommonRegs.ADC3R = pADCTriggerCfg->Trigger;
+ break;
+ }
+
+ case HRTIM_ADCTRIGGER_4:
+ {
+ hrtim_cr1 &= ~(HRTIM_CR1_ADC4USRC);
+ hrtim_cr1 |= ((pADCTriggerCfg->UpdateSource << 9U) & HRTIM_CR1_ADC4USRC);
+
+ /* Set the ADC trigger 4 source */
+ hhrtim->Instance->sCommonRegs.ADC4R = pADCTriggerCfg->Trigger;
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sCommonRegs.CR1 = hrtim_cr1;
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group8 Timer waveform configuration and functions
+ * @brief HRTIM timer configuration and control functions
+@verbatim
+ ===============================================================================
+ ##### HRTIM timer configuration and control functions #####
+ ===============================================================================
+ [..] This section provides functions used to configure and control a
+ HRTIM timer operating in waveform mode:
+ (+) Configure HRTIM timer general behavior
+ (+) Configure HRTIM timer event filtering
+ (+) Configure HRTIM timer deadtime insertion
+ (+) Configure HRTIM timer chopper mode
+ (+) Configure HRTIM timer burst DMA
+ (+) Configure HRTIM timer compare unit
+ (+) Configure HRTIM timer capture unit
+ (+) Configure HRTIM timer output
+ (+) Set HRTIM timer output level
+ (+) Enable HRTIM timer output
+ (+) Disable HRTIM timer output
+ (+) Start HRTIM timer
+ (+) Stop HRTIM timer
+ (+) Start HRTIM timer and enable interrupt
+ (+) Stop HRTIM timer and disable interrupt
+ (+) Start HRTIM timer and enable DMA transfer
+ (+) Stop HRTIM timer and disable DMA transfer
+ (+) Enable or disable the burst mode controller
+ (+) Start the burst mode controller (by software)
+ (+) Trigger a Capture (by software)
+ (+) Update the HRTIM timer preloadable registers (by software)
+ (+) Reset the HRTIM timer counter (by software)
+ (+) Start a burst DMA transfer
+ (+) Enable timer register update
+ (+) Disable timer register update
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the general behavior of a timer operating in waveform mode
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param pTimerCfg pointer to the timer configuration structure
+ * @note When the timer operates in waveform mode, all the features supported by
+ * the HRTIM are available without any limitation.
+ * @retval HAL status
+ * @note This function must be called before starting the timer
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformTimerConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ HRTIM_TimerCfgTypeDef * pTimerCfg)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+
+ /* Relevant for all HRTIM timers, including the master */
+ assert_param(IS_HRTIM_HALFMODE(pTimerCfg->HalfModeEnable));
+ assert_param(IS_HRTIM_SYNCSTART(pTimerCfg->StartOnSync));
+ assert_param(IS_HRTIM_SYNCRESET(pTimerCfg->ResetOnSync));
+ assert_param(IS_HRTIM_DACSYNC(pTimerCfg->DACSynchro));
+ assert_param(IS_HRTIM_PRELOAD(pTimerCfg->PreloadEnable));
+ assert_param(IS_HRTIM_TIMERBURSTMODE(pTimerCfg->BurstMode));
+ assert_param(IS_HRTIM_UPDATEONREPETITION(pTimerCfg->RepetitionUpdate));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ if (TimerIdx == HRTIM_TIMERINDEX_MASTER)
+ {
+ /* Check parameters */
+ assert_param(IS_HRTIM_UPDATEGATING_MASTER(pTimerCfg->UpdateGating));
+ assert_param(IS_HRTIM_MASTER_IT(pTimerCfg->InterruptRequests));
+ assert_param(IS_HRTIM_MASTER_DMA(pTimerCfg->DMARequests));
+
+ /* Configure master timer */
+ HRTIM_MasterWaveform_Config(hhrtim, pTimerCfg);
+ }
+ else
+ {
+ /* Check parameters */
+ assert_param(IS_HRTIM_UPDATEGATING_TIM(pTimerCfg->UpdateGating));
+ assert_param(IS_HRTIM_TIM_IT(pTimerCfg->InterruptRequests));
+ assert_param(IS_HRTIM_TIM_DMA(pTimerCfg->DMARequests));
+ assert_param(IS_HRTIM_TIMPUSHPULLMODE(pTimerCfg->PushPull));
+ assert_param(IS_HRTIM_TIMFAULTENABLE(pTimerCfg->FaultEnable));
+ assert_param(IS_HRTIM_TIMFAULTLOCK(pTimerCfg->FaultLock));
+ assert_param(IS_HRTIM_TIMDEADTIMEINSERTION(pTimerCfg->PushPull,
+ pTimerCfg->DeadTimeInsertion));
+ assert_param(IS_HRTIM_TIMDELAYEDPROTECTION(pTimerCfg->PushPull,
+ pTimerCfg->DelayedProtectionMode));
+ assert_param(IS_HRTIM_TIMUPDATETRIGGER(pTimerCfg->UpdateTrigger));
+ assert_param(IS_HRTIM_TIMRESETTRIGGER(pTimerCfg->ResetTrigger));
+ assert_param(IS_HRTIM_TIMUPDATEONRESET(pTimerCfg->ResetUpdate));
+
+ /* Configure timing unit */
+ HRTIM_TimingUnitWaveform_Config(hhrtim, TimerIdx, pTimerCfg);
+ }
+
+ /* Update timer parameters */
+ hhrtim->TimerParam[TimerIdx].InterruptRequests = pTimerCfg->InterruptRequests;
+ hhrtim->TimerParam[TimerIdx].DMARequests = pTimerCfg->DMARequests;
+ hhrtim->TimerParam[TimerIdx].DMASrcAddress = pTimerCfg->DMASrcAddress;
+ hhrtim->TimerParam[TimerIdx].DMADstAddress = pTimerCfg->DMADstAddress;
+ hhrtim->TimerParam[TimerIdx].DMASize = pTimerCfg->DMASize;
+
+ /* Force a software update */
+ HRTIM_ForceRegistersUpdate(hhrtim, TimerIdx);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the event filtering capabilities of a timer (blanking, windowing)
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param Event external event for which timer event filtering must be configured
+ * This parameter can be one of the following values:
+ * @arg HRTIM_EVENT_1: External event 1
+ * @arg HRTIM_EVENT_2: External event 2
+ * @arg HRTIM_EVENT_3: External event 3
+ * @arg HRTIM_EVENT_4: External event 4
+ * @arg HRTIM_EVENT_5: External event 5
+ * @arg HRTIM_EVENT_6: External event 6
+ * @arg HRTIM_EVENT_7: External event 7
+ * @arg HRTIM_EVENT_8: External event 8
+ * @arg HRTIM_EVENT_9: External event 9
+ * @arg HRTIM_EVENT_10: External event 10
+ * @param pTimerEventFilteringCfg pointer to the timer event filtering configuration structure
+ * @note This function must be called before starting the timer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_TimerEventFilteringConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Event,
+ HRTIM_TimerEventFilteringCfgTypeDef* pTimerEventFilteringCfg)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_EVENT(Event));
+ assert_param(IS_HRTIM_TIMEVENTFILTER(pTimerEventFilteringCfg->Filter));
+
+ assert_param(IS_HRTIM_TIMEVENTLATCH(pTimerEventFilteringCfg->Latch));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure timer event filtering capabilities */
+ switch (Event)
+ {
+ case HRTIM_EVENT_NONE:
+ {
+ CLEAR_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR1);
+ CLEAR_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR2);
+ break;
+ }
+
+ case HRTIM_EVENT_1:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR1, (HRTIM_EEFR1_EE1FLTR | HRTIM_EEFR1_EE1LTCH), (pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch));
+ break;
+ }
+
+ case HRTIM_EVENT_2:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR1, (HRTIM_EEFR1_EE2FLTR | HRTIM_EEFR1_EE2LTCH), ((pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch) << 6U) );
+ break;
+ }
+
+ case HRTIM_EVENT_3:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR1, (HRTIM_EEFR1_EE3FLTR | HRTIM_EEFR1_EE3LTCH), ((pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch) << 12U) );
+ break;
+ }
+
+ case HRTIM_EVENT_4:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR1, (HRTIM_EEFR1_EE4FLTR | HRTIM_EEFR1_EE4LTCH), ((pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch) << 18U) );
+ break;
+ }
+
+ case HRTIM_EVENT_5:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR1, (HRTIM_EEFR1_EE5FLTR | HRTIM_EEFR1_EE5LTCH), ((pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch) << 24U) );
+ break;
+ }
+
+ case HRTIM_EVENT_6:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR2, (HRTIM_EEFR2_EE6FLTR | HRTIM_EEFR2_EE6LTCH), (pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch) );
+ break;
+ }
+
+ case HRTIM_EVENT_7:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR2, (HRTIM_EEFR2_EE7FLTR | HRTIM_EEFR2_EE7LTCH), ((pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch) << 6U) );
+ break;
+ }
+
+ case HRTIM_EVENT_8:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR2, (HRTIM_EEFR2_EE8FLTR | HRTIM_EEFR2_EE8LTCH), ((pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch) << 12U) );
+ break;
+ }
+
+ case HRTIM_EVENT_9:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR2, (HRTIM_EEFR2_EE9FLTR | HRTIM_EEFR2_EE9LTCH), ((pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch) << 18U) );
+ break;
+ }
+
+ case HRTIM_EVENT_10:
+ {
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].EEFxR2, (HRTIM_EEFR2_EE10FLTR | HRTIM_EEFR2_EE10LTCH), ((pTimerEventFilteringCfg->Filter | pTimerEventFilteringCfg->Latch) << 24U) );
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the dead-time insertion feature for a timer
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param pDeadTimeCfg pointer to the deadtime insertion configuration structure
+ * @retval HAL status
+ * @note This function must be called before starting the timer
+ */
+HAL_StatusTypeDef HAL_HRTIM_DeadTimeConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ HRTIM_DeadTimeCfgTypeDef* pDeadTimeCfg)
+{
+ uint32_t hrtim_dtr;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_TIMDEADTIME_PRESCALERRATIO(pDeadTimeCfg->Prescaler));
+ assert_param(IS_HRTIM_TIMDEADTIME_RISINGSIGN(pDeadTimeCfg->RisingSign));
+ assert_param(IS_HRTIM_TIMDEADTIME_RISINGLOCK(pDeadTimeCfg->RisingLock));
+ assert_param(IS_HRTIM_TIMDEADTIME_RISINGSIGNLOCK(pDeadTimeCfg->RisingSignLock));
+ assert_param(IS_HRTIM_TIMDEADTIME_FALLINGSIGN(pDeadTimeCfg->FallingSign));
+ assert_param(IS_HRTIM_TIMDEADTIME_FALLINGLOCK(pDeadTimeCfg->FallingLock));
+ assert_param(IS_HRTIM_TIMDEADTIME_FALLINGSIGNLOCK(pDeadTimeCfg->FallingSignLock));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set timer deadtime configuration */
+ hrtim_dtr = (pDeadTimeCfg->Prescaler & HRTIM_DTR_DTPRSC);
+ hrtim_dtr |= (pDeadTimeCfg->RisingValue & HRTIM_DTR_DTR);
+ hrtim_dtr |= (pDeadTimeCfg->RisingSign & HRTIM_DTR_SDTR);
+ hrtim_dtr |= (pDeadTimeCfg->RisingSignLock & HRTIM_DTR_DTRSLK);
+ hrtim_dtr |= (pDeadTimeCfg->RisingLock & HRTIM_DTR_DTRLK);
+ hrtim_dtr |= ((pDeadTimeCfg->FallingValue << 16U) & HRTIM_DTR_DTF);
+ hrtim_dtr |= (pDeadTimeCfg->FallingSign & HRTIM_DTR_SDTF);
+ hrtim_dtr |= (pDeadTimeCfg->FallingSignLock & HRTIM_DTR_DTFSLK);
+ hrtim_dtr |= (pDeadTimeCfg->FallingLock & HRTIM_DTR_DTFLK);
+
+ /* Update the HRTIM registers */
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].DTxR, (
+ HRTIM_DTR_DTR | HRTIM_DTR_SDTR | HRTIM_DTR_DTPRSC |
+ HRTIM_DTR_DTRSLK | HRTIM_DTR_DTRLK | HRTIM_DTR_DTF |
+ HRTIM_DTR_SDTF | HRTIM_DTR_DTFSLK | HRTIM_DTR_DTFLK), hrtim_dtr);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the chopper mode feature for a timer
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param pChopperModeCfg pointer to the chopper mode configuration structure
+ * @retval HAL status
+ * @note This function must be called before configuring the timer output(s)
+ */
+HAL_StatusTypeDef HAL_HRTIM_ChopperModeConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ HRTIM_ChopperModeCfgTypeDef* pChopperModeCfg)
+{
+ uint32_t hrtim_chpr;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CHOPPER_PRESCALERRATIO(pChopperModeCfg->CarrierFreq));
+ assert_param(IS_HRTIM_CHOPPER_DUTYCYCLE(pChopperModeCfg->DutyCycle));
+ assert_param(IS_HRTIM_CHOPPER_PULSEWIDTH(pChopperModeCfg->StartPulse));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set timer choppe mode configuration */
+ hrtim_chpr = (pChopperModeCfg->CarrierFreq & HRTIM_CHPR_CARFRQ);
+ hrtim_chpr |= (pChopperModeCfg->DutyCycle & HRTIM_CHPR_CARDTY);
+ hrtim_chpr |= (pChopperModeCfg->StartPulse & HRTIM_CHPR_STRPW);
+
+ /* Update the HRTIM registers */
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].CHPxR, (HRTIM_CHPR_CARFRQ | HRTIM_CHPR_CARDTY |
+ HRTIM_CHPR_STRPW) ,
+ hrtim_chpr);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the burst DMA controller for a timer
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param RegistersToUpdate registers to be written by DMA
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_BURSTDMA_CR: HRTIM_MCR or HRTIM_TIMxCR
+ * @arg HRTIM_BURSTDMA_ICR: HRTIM_MICR or HRTIM_TIMxICR
+ * @arg HRTIM_BURSTDMA_DIER: HRTIM_MDIER or HRTIM_TIMxDIER
+ * @arg HRTIM_BURSTDMA_CNT: HRTIM_MCNT or HRTIM_TIMxCNT
+ * @arg HRTIM_BURSTDMA_PER: HRTIM_MPER or HRTIM_TIMxPER
+ * @arg HRTIM_BURSTDMA_REP: HRTIM_MREP or HRTIM_TIMxREP
+ * @arg HRTIM_BURSTDMA_CMP1: HRTIM_MCMP1 or HRTIM_TIMxCMP1
+ * @arg HRTIM_BURSTDMA_CMP2: HRTIM_MCMP2 or HRTIM_TIMxCMP2
+ * @arg HRTIM_BURSTDMA_CMP3: HRTIM_MCMP3 or HRTIM_TIMxCMP3
+ * @arg HRTIM_BURSTDMA_CMP4: HRTIM_MCMP4 or HRTIM_TIMxCMP4
+ * @arg HRTIM_BURSTDMA_DTR: HRTIM_TIMxDTR
+ * @arg HRTIM_BURSTDMA_SET1R: HRTIM_TIMxSET1R
+ * @arg HRTIM_BURSTDMA_RST1R: HRTIM_TIMxRST1R
+ * @arg HRTIM_BURSTDMA_SET2R: HRTIM_TIMxSET2R
+ * @arg HRTIM_BURSTDMA_RST2R: HRTIM_TIMxRST2R
+ * @arg HRTIM_BURSTDMA_EEFR1: HRTIM_TIMxEEFR1
+ * @arg HRTIM_BURSTDMA_EEFR2: HRTIM_TIMxEEFR2
+ * @arg HRTIM_BURSTDMA_RSTR: HRTIM_TIMxRSTR
+ * @arg HRTIM_BURSTDMA_CHPR: HRTIM_TIMxCHPR
+ * @arg HRTIM_BURSTDMA_OUTR: HRTIM_TIMxOUTR
+ * @arg HRTIM_BURSTDMA_FLTR: HRTIM_TIMxFLTR
+ * @retval HAL status
+ * @note This function must be called before starting the timer
+ */
+HAL_StatusTypeDef HAL_HRTIM_BurstDMAConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t RegistersToUpdate)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_BURSTDMA(TimerIdx, RegistersToUpdate));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Set the burst DMA timer update register */
+ switch (TimerIdx)
+ {
+ case HRTIM_TIMERINDEX_TIMER_A:
+ {
+ hhrtim->Instance->sCommonRegs.BDTAUPR = RegistersToUpdate;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_B:
+ {
+ hhrtim->Instance->sCommonRegs.BDTBUPR = RegistersToUpdate;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_C:
+ {
+ hhrtim->Instance->sCommonRegs.BDTCUPR = RegistersToUpdate;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_D:
+ {
+ hhrtim->Instance->sCommonRegs.BDTDUPR = RegistersToUpdate;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_E:
+ {
+ hhrtim->Instance->sCommonRegs.BDTEUPR = RegistersToUpdate;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_MASTER:
+ {
+ hhrtim->Instance->sCommonRegs.BDMUPR = RegistersToUpdate;
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the compare unit of a timer operating in waveform mode
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CompareUnit Compare unit to configure
+ * This parameter can be one of the following values:
+ * @arg HRTIM_COMPAREUNIT_1: Compare unit 1
+ * @arg HRTIM_COMPAREUNIT_2: Compare unit 2
+ * @arg HRTIM_COMPAREUNIT_3: Compare unit 3
+ * @arg HRTIM_COMPAREUNIT_4: Compare unit 4
+ * @param pCompareCfg pointer to the compare unit configuration structure
+ * @note When auto delayed mode is required for compare unit 2 or compare unit 4,
+ * application has to configure separately the capture unit. Capture unit
+ * to configure in that case depends on the compare unit auto delayed mode
+ * is applied to (see below):
+ * Auto delayed on output compare 2: capture unit 1 must be configured
+ * Auto delayed on output compare 4: capture unit 2 must be configured
+ * @retval HAL status
+ * @note This function must be called before starting the timer
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformCompareConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CompareUnit,
+ HRTIM_CompareCfgTypeDef* pCompareCfg)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure the compare unit */
+ if (TimerIdx == HRTIM_TIMERINDEX_MASTER)
+ {
+ switch (CompareUnit)
+ {
+ case HRTIM_COMPAREUNIT_1:
+ {
+ hhrtim->Instance->sMasterRegs.MCMP1R = pCompareCfg->CompareValue;
+ break;
+ }
+
+ case HRTIM_COMPAREUNIT_2:
+ {
+ hhrtim->Instance->sMasterRegs.MCMP2R = pCompareCfg->CompareValue;
+ break;
+ }
+
+ case HRTIM_COMPAREUNIT_3:
+ {
+ hhrtim->Instance->sMasterRegs.MCMP3R = pCompareCfg->CompareValue;
+ break;
+ }
+
+ case HRTIM_COMPAREUNIT_4:
+ {
+ hhrtim->Instance->sMasterRegs.MCMP4R = pCompareCfg->CompareValue;
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ }
+ else
+ {
+ switch (CompareUnit)
+ {
+ case HRTIM_COMPAREUNIT_1:
+ {
+ /* Set the compare value */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP1xR = pCompareCfg->CompareValue;
+ break;
+ }
+
+ case HRTIM_COMPAREUNIT_2:
+ {
+ /* Check parameters */
+ assert_param(IS_HRTIM_COMPAREUNIT_AUTODELAYEDMODE(CompareUnit, pCompareCfg->AutoDelayedMode));
+
+ /* Set the compare value */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP2xR = pCompareCfg->CompareValue;
+
+ if (pCompareCfg->AutoDelayedMode != HRTIM_AUTODELAYEDMODE_REGULAR)
+ {
+ /* Configure auto-delayed mode */
+ /* DELCMP2 bitfield must be reset when reprogrammed from one value */
+ /* to the other to reinitialize properly the auto-delayed mechanism */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR &= ~HRTIM_TIMCR_DELCMP2;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR |= pCompareCfg->AutoDelayedMode;
+
+ /* Set the compare value for timeout compare unit (if any) */
+ if (pCompareCfg->AutoDelayedMode == HRTIM_AUTODELAYEDMODE_AUTODELAYED_TIMEOUTCMP1)
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP1xR = pCompareCfg->AutoDelayedTimeout;
+ }
+ else if (pCompareCfg->AutoDelayedMode == HRTIM_AUTODELAYEDMODE_AUTODELAYED_TIMEOUTCMP3)
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP3xR = pCompareCfg->AutoDelayedTimeout;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ }
+ else
+ {
+ /* Clear HRTIM_TIMxCR.DELCMP2 bitfield */
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR, HRTIM_TIMCR_DELCMP2, 0U);
+ }
+ break;
+ }
+
+ case HRTIM_COMPAREUNIT_3:
+ {
+ /* Set the compare value */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP3xR = pCompareCfg->CompareValue;
+ break;
+ }
+
+ case HRTIM_COMPAREUNIT_4:
+ {
+ /* Check parameters */
+ assert_param(IS_HRTIM_COMPAREUNIT_AUTODELAYEDMODE(CompareUnit, pCompareCfg->AutoDelayedMode));
+
+ /* Set the compare value */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP4xR = pCompareCfg->CompareValue;
+
+ if (pCompareCfg->AutoDelayedMode != HRTIM_AUTODELAYEDMODE_REGULAR)
+ {
+ /* Configure auto-delayed mode */
+ /* DELCMP4 bitfield must be reset when reprogrammed from one value */
+ /* to the other to reinitialize properly the auto-delayed mechanism */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR &= ~HRTIM_TIMCR_DELCMP4;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR |= (pCompareCfg->AutoDelayedMode << 2U);
+
+ /* Set the compare value for timeout compare unit (if any) */
+ if (pCompareCfg->AutoDelayedMode == HRTIM_AUTODELAYEDMODE_AUTODELAYED_TIMEOUTCMP1)
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP1xR = pCompareCfg->AutoDelayedTimeout;
+ }
+ else if (pCompareCfg->AutoDelayedMode == HRTIM_AUTODELAYEDMODE_AUTODELAYED_TIMEOUTCMP3)
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].CMP3xR = pCompareCfg->AutoDelayedTimeout;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ }
+ else
+ {
+ /* Clear HRTIM_TIMxCR.DELCMP4 bitfield */
+ MODIFY_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR, HRTIM_TIMCR_DELCMP4, 0U);
+ }
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ }
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the capture unit of a timer operating in waveform mode
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureUnit Capture unit to configure
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @param pCaptureCfg pointer to the compare unit configuration structure
+ * @retval HAL status
+ * @note This function must be called before starting the timer
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformCaptureConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureUnit,
+ HRTIM_CaptureCfgTypeDef* pCaptureCfg)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_CAPTURETRIGGER(TimerIdx, pCaptureCfg->Trigger));
+
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure the capture unit */
+ switch (CaptureUnit)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ WRITE_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR, pCaptureCfg->Trigger);
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ WRITE_REG(hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR, pCaptureCfg->Trigger);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the output of a timer operating in waveform mode
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param Output Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @param pOutputCfg pointer to the timer output configuration structure
+ * @retval HAL status
+ * @note This function must be called before configuring the timer and after
+ * configuring the deadtime insertion feature (if required).
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformOutputConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Output,
+ HRTIM_OutputCfgTypeDef * pOutputCfg)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, Output));
+ assert_param(IS_HRTIM_OUTPUTPOLARITY(pOutputCfg->Polarity));
+ assert_param(IS_HRTIM_OUTPUTIDLELEVEL(pOutputCfg->IdleLevel));
+ assert_param(IS_HRTIM_OUTPUTIDLEMODE(pOutputCfg->IdleMode));
+ assert_param(IS_HRTIM_OUTPUTFAULTLEVEL(pOutputCfg->FaultLevel));
+ assert_param(IS_HRTIM_OUTPUTCHOPPERMODE(pOutputCfg->ChopperModeEnable));
+ assert_param(IS_HRTIM_OUTPUTBURSTMODEENTRY(pOutputCfg->BurstModeEntryDelayed));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Configure the timer output */
+ HRTIM_OutputConfig(hhrtim,
+ TimerIdx,
+ Output,
+ pOutputCfg);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Force the timer output to its active or inactive state
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param Output Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @param OutputLevel indicates whether the output is forced to its active or inactive level
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUTLEVEL_ACTIVE: output is forced to its active level
+ * @arg HRTIM_OUTPUTLEVEL_INACTIVE: output is forced to its inactive level
+ * @retval HAL status
+ * @note The 'software set/reset trigger' bit in the output set/reset registers
+ * is automatically reset by hardware
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformSetOutputLevel(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Output,
+ uint32_t OutputLevel)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, Output));
+ assert_param(IS_HRTIM_OUTPUTLEVEL(OutputLevel));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Force timer output level */
+ switch (Output)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ if (OutputLevel == HRTIM_OUTPUTLEVEL_ACTIVE)
+ {
+ /* Force output to its active state */
+ SET_BIT(hhrtim->Instance->sTimerxRegs[TimerIdx].SETx1R,HRTIM_SET1R_SST);
+ }
+ else
+ {
+ /* Force output to its inactive state */
+ SET_BIT(hhrtim->Instance->sTimerxRegs[TimerIdx].RSTx1R, HRTIM_RST1R_SRT);
+ }
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ if (OutputLevel == HRTIM_OUTPUTLEVEL_ACTIVE)
+ {
+ /* Force output to its active state */
+ SET_BIT(hhrtim->Instance->sTimerxRegs[TimerIdx].SETx2R, HRTIM_SET2R_SST);
+ }
+ else
+ {
+ /* Force output to its inactive state */
+ SET_BIT(hhrtim->Instance->sTimerxRegs[TimerIdx].RSTx2R, HRTIM_RST2R_SRT);
+ }
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the generation of the waveform signal on the designated output(s)
+ * Outputs can be combined (ORed) to allow for simultaneous output enabling.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param OutputsToStart Timer output(s) to enable
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformOutputStart(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t OutputsToStart)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_OUTPUT(OutputsToStart));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable the HRTIM outputs */
+ hhrtim->Instance->sCommonRegs.OENR |= (OutputsToStart);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the generation of the waveform signal on the designated output(s)
+ * Outputs can be combined (ORed) to allow for simultaneous output disabling.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param OutputsToStop Timer output(s) to disable
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformOutputStop(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t OutputsToStop)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_OUTPUT(OutputsToStop));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable the HRTIM outputs */
+ hhrtim->Instance->sCommonRegs.ODISR |= (OutputsToStop);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the counter of the designated timer(s) operating in waveform mode
+ * Timers can be combined (ORed) to allow for simultaneous counter start.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers Timer counter(s) to start
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERID_MASTER
+ * @arg HRTIM_TIMERID_TIMER_A
+ * @arg HRTIM_TIMERID_TIMER_B
+ * @arg HRTIM_TIMERID_TIMER_C
+ * @arg HRTIM_TIMERID_TIMER_D
+ * @arg HRTIM_TIMERID_TIMER_E
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformCountStart(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Timers)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERID(Timers));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable timer(s) counter */
+ hhrtim->Instance->sMasterRegs.MCR |= (Timers);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the counter of the designated timer(s) operating in waveform mode
+ * Timers can be combined (ORed) to allow for simultaneous counter stop.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers Timer counter(s) to stop
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERID_MASTER
+ * @arg HRTIM_TIMERID_A
+ * @arg HRTIM_TIMERID_B
+ * @arg HRTIM_TIMERID_C
+ * @arg HRTIM_TIMERID_D
+ * @arg HRTIM_TIMERID_E
+ * @retval HAL status
+ * @note The counter of a timer is stopped only if all timer outputs are disabled
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformCountStop(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Timers)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERID(Timers));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable timer(s) counter */
+ hhrtim->Instance->sMasterRegs.MCR &= ~(Timers);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the counter of the designated timer(s) operating in waveform mode
+ * Timers can be combined (ORed) to allow for simultaneous counter start.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers Timer counter(s) to start
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERID_MASTER
+ * @arg HRTIM_TIMERID_A
+ * @arg HRTIM_TIMERID_B
+ * @arg HRTIM_TIMERID_C
+ * @arg HRTIM_TIMERID_D
+ * @arg HRTIM_TIMERID_E
+ * @note HRTIM interrupts (e.g. faults interrupts) and interrupts related
+ * to the timers to start are enabled within this function.
+ * Interrupts to enable are selected through HAL_HRTIM_WaveformTimerConfig
+ * function.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformCountStart_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Timers)
+{
+ uint8_t timer_idx;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERID(Timers));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable HRTIM interrupts (if required) */
+ __HAL_HRTIM_ENABLE_IT(hhrtim, hhrtim->Init.HRTIMInterruptResquests);
+
+ /* Enable master timer related interrupts (if required) */
+ if ((Timers & HRTIM_TIMERID_MASTER) != 0U)
+ {
+ __HAL_HRTIM_MASTER_ENABLE_IT(hhrtim,
+ hhrtim->TimerParam[HRTIM_TIMERINDEX_MASTER].InterruptRequests);
+ }
+
+ /* Enable timing unit related interrupts (if required) */
+ for (timer_idx = HRTIM_TIMERINDEX_TIMER_A ;
+ timer_idx < HRTIM_TIMERINDEX_MASTER ;
+ timer_idx++)
+ {
+ if ((Timers & TimerIdxToTimerId[timer_idx]) != 0U)
+ {
+ __HAL_HRTIM_TIMER_ENABLE_IT(hhrtim,
+ timer_idx,
+ hhrtim->TimerParam[timer_idx].InterruptRequests);
+ }
+ }
+
+ /* Enable timer(s) counter */
+ hhrtim->Instance->sMasterRegs.MCR |= (Timers);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;}
+
+/**
+ * @brief Stop the counter of the designated timer(s) operating in waveform mode
+ * Timers can be combined (ORed) to allow for simultaneous counter stop.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers Timer counter(s) to stop
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERID_MASTER
+ * @arg HRTIM_TIMERID_A
+ * @arg HRTIM_TIMERID_B
+ * @arg HRTIM_TIMERID_C
+ * @arg HRTIM_TIMERID_D
+ * @arg HRTIM_TIMERID_E
+ * @retval HAL status
+ * @note The counter of a timer is stopped only if all timer outputs are disabled
+ * @note All enabled timer related interrupts are disabled.
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformCountStop_IT(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Timers)
+{
+ /* ++ WA */
+ __IO uint32_t delai = (uint32_t)(0x17FU);
+ /* -- WA */
+
+ uint8_t timer_idx;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERID(Timers));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Disable HRTIM interrupts (if required) */
+ __HAL_HRTIM_DISABLE_IT(hhrtim, hhrtim->Init.HRTIMInterruptResquests);
+
+ /* Disable master timer related interrupts (if required) */
+ if ((Timers & HRTIM_TIMERID_MASTER) != 0U)
+ {
+ /* Interrupts enable flag must be cleared one by one */
+ __HAL_HRTIM_MASTER_DISABLE_IT(hhrtim, hhrtim->TimerParam[HRTIM_TIMERINDEX_MASTER].InterruptRequests);
+ }
+
+ /* Disable timing unit related interrupts (if required) */
+ for (timer_idx = HRTIM_TIMERINDEX_TIMER_A ;
+ timer_idx < HRTIM_TIMERINDEX_MASTER ;
+ timer_idx++)
+ {
+ if ((Timers & TimerIdxToTimerId[timer_idx]) != 0U)
+ {
+ __HAL_HRTIM_TIMER_DISABLE_IT(hhrtim, timer_idx, hhrtim->TimerParam[timer_idx].InterruptRequests);
+ }
+ }
+
+ /* ++ WA */
+ do { delai--; } while (delai != 0U);
+ /* -- WA */
+
+ /* Disable timer(s) counter */
+ hhrtim->Instance->sMasterRegs.MCR &= ~(Timers);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the counter of the designated timer(s) operating in waveform mode
+ * Timers can be combined (ORed) to allow for simultaneous counter start.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers Timer counter(s) to start
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERID_MASTER
+ * @arg HRTIM_TIMERID_TIMER_A
+ * @arg HRTIM_TIMERID_TIMER_B
+ * @arg HRTIM_TIMERID_TIMER_C
+ * @arg HRTIM_TIMERID_TIMER_D
+ * @arg HRTIM_TIMERID_TIMER_E
+ * @retval HAL status
+ * @note This function enables the dma request(s) mentionned in the timer
+ * configuration data structure for every timers to start.
+ * @note The source memory address, the destination memory address and the
+ * size of each DMA transfer are specified at timer configuration time
+ * (see HAL_HRTIM_WaveformTimerConfig)
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformCountStart_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Timers)
+{
+ uint8_t timer_idx;
+ DMA_HandleTypeDef * hdma;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERID(Timers));
+
+ if((hhrtim->State == HAL_HRTIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ if (((Timers & HRTIM_TIMERID_MASTER) != (uint32_t)RESET) &&
+ (hhrtim->TimerParam[HRTIM_TIMERINDEX_MASTER].DMARequests != 0U))
+ {
+ /* Set the DMA error callback */
+ hhrtim->hdmaMaster->XferErrorCallback = HRTIM_DMAError ;
+
+ /* Set the DMA transfer completed callback */
+ hhrtim->hdmaMaster->XferCpltCallback = HRTIM_DMAMasterCplt;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hhrtim->hdmaMaster,
+ hhrtim->TimerParam[HRTIM_TIMERINDEX_MASTER].DMASrcAddress,
+ hhrtim->TimerParam[HRTIM_TIMERINDEX_MASTER].DMADstAddress,
+ hhrtim->TimerParam[HRTIM_TIMERINDEX_MASTER].DMASize) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer DMA request */
+ __HAL_HRTIM_MASTER_ENABLE_DMA(hhrtim,
+ hhrtim->TimerParam[HRTIM_TIMERINDEX_MASTER].DMARequests);
+ }
+
+ for (timer_idx = HRTIM_TIMERINDEX_TIMER_A ;
+ timer_idx < HRTIM_TIMERINDEX_MASTER ;
+ timer_idx++)
+ {
+ if (((Timers & TimerIdxToTimerId[timer_idx]) != (uint32_t)RESET) &&
+ (hhrtim->TimerParam[timer_idx].DMARequests != 0U))
+ {
+ /* Get the timer DMA handler */
+ hdma = HRTIM_GetDMAHandleFromTimerIdx(hhrtim, timer_idx);
+
+ if (hdma == NULL)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Set the DMA error callback */
+ hdma->XferErrorCallback = HRTIM_DMAError ;
+
+ /* Set the DMA transfer completed callback */
+ hdma->XferCpltCallback = HRTIM_DMATimerxCplt;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hdma,
+ hhrtim->TimerParam[timer_idx].DMASrcAddress,
+ hhrtim->TimerParam[timer_idx].DMADstAddress,
+ hhrtim->TimerParam[timer_idx].DMASize) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the timer DMA request */
+ __HAL_HRTIM_TIMER_ENABLE_DMA(hhrtim,
+ timer_idx,
+ hhrtim->TimerParam[timer_idx].DMARequests);
+ }
+ }
+
+ /* Enable the timer counter */
+ __HAL_HRTIM_ENABLE(hhrtim, Timers);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the counter of the designated timer(s) operating in waveform mode
+ * Timers can be combined (ORed) to allow for simultaneous counter stop.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers Timer counter(s) to stop
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERID_MASTER
+ * @arg HRTIM_TIMERID_TIMER_A
+ * @arg HRTIM_TIMERID_TIMER_B
+ * @arg HRTIM_TIMERID_TIMER_C
+ * @arg HRTIM_TIMERID_TIMER_D
+ * @arg HRTIM_TIMERID_TIMER_E
+ * @retval HAL status
+ * @note The counter of a timer is stopped only if all timer outputs are disabled
+ * @note All enabled timer related DMA requests are disabled.
+ */
+HAL_StatusTypeDef HAL_HRTIM_WaveformCountStop_DMA(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Timers)
+{
+ uint8_t timer_idx;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERID(Timers));
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ if (((Timers & HRTIM_TIMERID_MASTER) != 0U) &&
+ (hhrtim->TimerParam[HRTIM_TIMERINDEX_MASTER].DMARequests != 0U))
+ {
+ /* Disable the DMA */
+ if (HAL_DMA_Abort(hhrtim->hdmaMaster) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+ }
+ else
+ {
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+ /* Disable the DMA request(s) */
+ __HAL_HRTIM_MASTER_DISABLE_DMA(hhrtim,
+ hhrtim->TimerParam[HRTIM_TIMERINDEX_MASTER].DMARequests);
+ }
+ }
+
+ for (timer_idx = HRTIM_TIMERINDEX_TIMER_A ;
+ timer_idx < HRTIM_TIMERINDEX_MASTER ;
+ timer_idx++)
+ {
+ if (((Timers & TimerIdxToTimerId[timer_idx]) != 0U) &&
+ (hhrtim->TimerParam[timer_idx].DMARequests != 0U))
+ {
+ /* Get the timer DMA handler */
+ /* Disable the DMA */
+ if (HAL_DMA_Abort(HRTIM_GetDMAHandleFromTimerIdx(hhrtim, timer_idx)) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+ }
+ else
+ {
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Disable the DMA request(s) */
+ __HAL_HRTIM_TIMER_DISABLE_DMA(hhrtim,
+ timer_idx,
+ hhrtim->TimerParam[timer_idx].DMARequests);
+ }
+ }
+ }
+
+ /* Disable the timer counter */
+ __HAL_HRTIM_DISABLE(hhrtim, Timers);
+
+ if (hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Enable or disables the HRTIM burst mode controller.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Enable Burst mode controller enabling
+ * This parameter can be one of the following values:
+ * @arg HRTIM_BURSTMODECTL_ENABLED: Burst mode enabled
+ * @arg HRTIM_BURSTMODECTL_DISABLED: Burst mode disabled
+ * @retval HAL status
+ * @note This function must be called after starting the timer(s)
+ */
+HAL_StatusTypeDef HAL_HRTIM_BurstModeCtl(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Enable)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_BURSTMODECTL(Enable));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable/Disable the burst mode controller */
+ MODIFY_REG(hhrtim->Instance->sCommonRegs.BMCR, HRTIM_BMCR_BME, Enable);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Trig the burst mode operation.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_BurstModeSoftwareTrigger(HRTIM_HandleTypeDef *hhrtim)
+{
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Software trigger of the burst mode controller */
+ SET_BIT(hhrtim->Instance->sCommonRegs.BMTRGR, HRTIM_BMTRGR_SW);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Trig a software capture on the designed capture unit
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureUnit Capture unit to trig
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @retval HAL status
+ * @note The 'software capture' bit in the capure configuration register is
+ * automatically reset by hardware
+ */
+HAL_StatusTypeDef HAL_HRTIM_SoftwareCapture(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureUnit)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CAPTUREUNIT(CaptureUnit));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Force a software capture on concerned capture unit */
+ switch (CaptureUnit)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ SET_BIT(hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xCR, HRTIM_CPT1CR_SWCPT);
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ SET_BIT(hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xCR, HRTIM_CPT2CR_SWCPT);
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Trig the update of the registers of one or several timers
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers timers concerned with the software register update
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERUPDATE_MASTER
+ * @arg HRTIM_TIMERUPDATE_A
+ * @arg HRTIM_TIMERUPDATE_B
+ * @arg HRTIM_TIMERUPDATE_C
+ * @arg HRTIM_TIMERUPDATE_D
+ * @arg HRTIM_TIMERUPDATE_E
+ * @retval HAL status
+ * @note The 'software update' bits in the HRTIM conrol register 2 register are
+ * automatically reset by hardware
+ */
+HAL_StatusTypeDef HAL_HRTIM_SoftwareUpdate(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Timers)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMERUPDATE(Timers));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Force timer(s) registers update */
+ hhrtim->Instance->sCommonRegs.CR2 |= Timers;
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Trig the reset of one or several timers
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers timers concerned with the software counter reset
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERRESET_MASTER
+ * @arg HRTIM_TIMERRESET_TIMER_A
+ * @arg HRTIM_TIMERRESET_TIMER_B
+ * @arg HRTIM_TIMERRESET_TIMER_C
+ * @arg HRTIM_TIMERRESET_TIMER_D
+ * @arg HRTIM_TIMERRESET_TIMER_E
+ * @retval HAL status
+ * @note The 'software reset' bits in the HRTIM conrol register 2 are
+ * automatically reset by hardware
+ */
+HAL_StatusTypeDef HAL_HRTIM_SoftwareReset(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Timers)
+{
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMERRESET(Timers));
+
+ if(hhrtim->State == HAL_HRTIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Force timer(s) registers reset */
+ hhrtim->Instance->sCommonRegs.CR2 = Timers;
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start a burst DMA operation to update HRTIM control registers content
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param BurstBufferAddress address of the buffer the HRTIM control registers
+ * content will be updated from.
+ * @param BurstBufferLength size (in WORDS) of the burst buffer.
+ * @retval HAL status
+ * @note The TimerIdx parameter determines the dma channel to be used by the
+ * DMA burst controller (see below)
+ * HRTIM_TIMERINDEX_MASTER: DMA channel 2 is used by the DMA burst controller
+ * HRTIM_TIMERINDEX_TIMER_A: DMA channel 3 is used by the DMA burst controller
+ * HRTIM_TIMERINDEX_TIMER_B: DMA channel 4 is used by the DMA burst controller
+ * HRTIM_TIMERINDEX_TIMER_C: DMA channel 5 is used by the DMA burst controller
+ * HRTIM_TIMERINDEX_TIMER_D: DMA channel 6 is used by the DMA burst controller
+ * HRTIM_TIMERINDEX_TIMER_E: DMA channel 7 is used by the DMA burst controller
+ */
+HAL_StatusTypeDef HAL_HRTIM_BurstDMATransfer(HRTIM_HandleTypeDef *hhrtim,
+ uint32_t TimerIdx,
+ uint32_t BurstBufferAddress,
+ uint32_t BurstBufferLength)
+{
+ DMA_HandleTypeDef * hdma;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERINDEX(TimerIdx));
+
+ if((hhrtim->State == HAL_HRTIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ if((hhrtim->State == HAL_HRTIM_STATE_READY))
+ {
+ if((BurstBufferAddress == 0U ) || (BurstBufferLength == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+ }
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ /* Get the timer DMA handler */
+ hdma = HRTIM_GetDMAHandleFromTimerIdx(hhrtim, TimerIdx);
+
+ if (hdma == NULL)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ /* Set the DMA transfer completed callback */
+ hdma->XferCpltCallback = HRTIM_BurstDMACplt;
+
+ /* Set the DMA error callback */
+ hdma->XferErrorCallback = HRTIM_DMAError ;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hdma,
+ BurstBufferAddress,
+ (uint32_t)&(hhrtim->Instance->sCommonRegs.BDMADR),
+ BurstBufferLength) != HAL_OK)
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_ERROR;
+ }
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the transfer from preload to active registers for one
+ * or several timing units (including master timer).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers Timer(s) concerned by the register preload enabling command
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERUPDATE_MASTER
+ * @arg HRTIM_TIMERUPDATE_A
+ * @arg HRTIM_TIMERUPDATE_B
+ * @arg HRTIM_TIMERUPDATE_C
+ * @arg HRTIM_TIMERUPDATE_D
+ * @arg HRTIM_TIMERUPDATE_E
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_UpdateEnable(HRTIM_HandleTypeDef *hhrtim,
+ uint32_t Timers)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERUPDATE(Timers));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable timer(s) registers update */
+ hhrtim->Instance->sCommonRegs.CR1 &= ~(Timers);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+ }
+
+/**
+ * @brief Disable the transfer from preload to active registers for one
+ * or several timing units (including master timer).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Timers Timer(s) concerned by the register preload disabling command
+ * This parameter can be any combination of the following values:
+ * @arg HRTIM_TIMERUPDATE_MASTER
+ * @arg HRTIM_TIMERUPDATE_A
+ * @arg HRTIM_TIMERUPDATE_B
+ * @arg HRTIM_TIMERUPDATE_C
+ * @arg HRTIM_TIMERUPDATE_D
+ * @arg HRTIM_TIMERUPDATE_E
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_UpdateDisable(HRTIM_HandleTypeDef *hhrtim,
+ uint32_t Timers)
+{
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMERUPDATE(Timers));
+
+ /* Process Locked */
+ __HAL_LOCK(hhrtim);
+
+ hhrtim->State = HAL_HRTIM_STATE_BUSY;
+
+ /* Enable timer(s) registers update */
+ hhrtim->Instance->sCommonRegs.CR1 |= (Timers);
+
+ hhrtim->State = HAL_HRTIM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ return HAL_OK;
+ }
+
+/**
+ * @}
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group9 Peripheral state functions
+ * @brief Peripheral State functions
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..] This section provides functions used to get HRTIM or HRTIM timer
+ specific information:
+ (+) Get HRTIM HAL state
+ (+) Get captured value
+ (+) Get HRTIM timer output level
+ (+) Get HRTIM timer output state
+ (+) Get delayed protection status
+ (+) Get burst status
+ (+) Get current push-pull status
+ (+) Get idle push-pull status
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the HRTIM HAL state
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval HAL state
+ */
+HAL_HRTIM_StateTypeDef HAL_HRTIM_GetState(HRTIM_HandleTypeDef* hhrtim)
+{
+ /* Return HRTIM state */
+ return hhrtim->State;
+}
+
+/**
+ * @brief Return actual value of the capture register of the designated capture unit
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param CaptureUnit Capture unit to trig
+ * This parameter can be one of the following values:
+ * @arg HRTIM_CAPTUREUNIT_1: Capture unit 1
+ * @arg HRTIM_CAPTUREUNIT_2: Capture unit 2
+ * @retval Captured value
+ */
+uint32_t HAL_HRTIM_GetCapturedValue(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureUnit)
+{
+ uint32_t captured_value;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+ assert_param(IS_HRTIM_CAPTUREUNIT(CaptureUnit));
+
+ /* Read captured value */
+ switch (CaptureUnit)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ captured_value = hhrtim->Instance->sTimerxRegs[TimerIdx].CPT1xR;
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ captured_value = hhrtim->Instance->sTimerxRegs[TimerIdx].CPT2xR;
+ break;
+ }
+
+ default:
+ {
+ captured_value = 0xFFFFFFFFUL;
+
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+ break;
+ }
+
+ }
+
+ return captured_value;
+}
+
+
+/**
+ * @brief Return actual level (active or inactive) of the designated output
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param Output Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval Output level
+ * @note Returned output level is taken before the output stage (chopper,
+ * polarity).
+ */
+uint32_t HAL_HRTIM_WaveformGetOutputLevel(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Output)
+{
+ uint32_t output_level = (uint32_t)RESET;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, Output));
+
+ /* Read the output level */
+ switch (Output)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ if ((hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxISR & HRTIM_TIMISR_O1CPY) != (uint32_t)RESET)
+ {
+ output_level = HRTIM_OUTPUTLEVEL_ACTIVE;
+ }
+ else
+ {
+ output_level = HRTIM_OUTPUTLEVEL_INACTIVE;
+ }
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ if ((hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxISR & HRTIM_TIMISR_O2CPY) != (uint32_t)RESET)
+ {
+ output_level = HRTIM_OUTPUTLEVEL_ACTIVE;
+ }
+ else
+ {
+ output_level = HRTIM_OUTPUTLEVEL_INACTIVE;
+ }
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return (uint32_t)HAL_ERROR;
+ }
+
+ return output_level;
+}
+
+/**
+ * @brief Return actual state (RUN, IDLE, FAULT) of the designated output
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param Output Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval Output state
+ */
+uint32_t HAL_HRTIM_WaveformGetOutputState(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Output)
+{
+ uint32_t output_bit = (uint32_t)RESET;
+ uint32_t output_state;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, Output));
+
+ /* Set output state according to output control status and output disable status */
+ switch (Output)
+ {
+ case HRTIM_OUTPUT_TA1:
+ {
+ output_bit = HRTIM_OENR_TA1OEN;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ {
+ output_bit = HRTIM_OENR_TA2OEN;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TB1:
+ {
+ output_bit = HRTIM_OENR_TB1OEN;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TB2:
+ {
+ output_bit = HRTIM_OENR_TB2OEN;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TC1:
+ {
+ output_bit = HRTIM_OENR_TC1OEN;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TC2:
+ {
+ output_bit = HRTIM_OENR_TC2OEN;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TD1:
+ {
+ output_bit = HRTIM_OENR_TD1OEN;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TD2:
+ {
+ output_bit = HRTIM_OENR_TD2OEN;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TE1:
+ {
+ output_bit = HRTIM_OENR_TE1OEN;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TE2:
+ {
+ output_bit = HRTIM_OENR_TE2OEN;
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return (uint32_t)HAL_ERROR;
+ }
+
+ if ((hhrtim->Instance->sCommonRegs.OENR & output_bit) != (uint32_t)RESET)
+ {
+ /* Output is enabled: output in RUN state (whatever ouput disable status is)*/
+ output_state = HRTIM_OUTPUTSTATE_RUN;
+ }
+ else
+ {
+ if ((hhrtim->Instance->sCommonRegs.ODSR & output_bit) != (uint32_t)RESET)
+ {
+ /* Output is disabled: output in FAULT state */
+ output_state = HRTIM_OUTPUTSTATE_FAULT;
+ }
+ else
+ {
+ /* Output is disabled: output in IDLE state */
+ output_state = HRTIM_OUTPUTSTATE_IDLE;
+ }
+ }
+
+ return(output_state);
+}
+
+/**
+ * @brief Return the level (active or inactive) of the designated output
+ * when the delayed protection was triggered.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @param Output Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval Delayed protection status
+ */
+uint32_t HAL_HRTIM_GetDelayedProtectionStatus(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Output)
+{
+ uint32_t delayed_protection_status = (uint32_t)RESET;
+
+ /* Check parameters */
+ assert_param(IS_HRTIM_TIMER_OUTPUT(TimerIdx, Output));
+
+ /* Read the delayed protection status */
+ switch (Output)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ if ((hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxISR & HRTIM_TIMISR_O1STAT) != (uint32_t)RESET)
+ {
+ /* Output 1 was active when the delayed idle protection was triggered */
+ delayed_protection_status = HRTIM_OUTPUTLEVEL_ACTIVE;
+ }
+ else
+ {
+ /* Output 1 was inactive when the delayed idle protection was triggered */
+ delayed_protection_status = HRTIM_OUTPUTLEVEL_INACTIVE;
+ }
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ if ((hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxISR & HRTIM_TIMISR_O2STAT) != (uint32_t)RESET)
+ {
+ /* Output 2 was active when the delayed idle protection was triggered */
+ delayed_protection_status = HRTIM_OUTPUTLEVEL_ACTIVE;
+ }
+ else
+ {
+ /* Output 2 was inactive when the delayed idle protection was triggered */
+ delayed_protection_status = HRTIM_OUTPUTLEVEL_INACTIVE;
+ }
+ break;
+ }
+
+ default:
+ {
+ hhrtim->State = HAL_HRTIM_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hhrtim);
+
+ break;
+ }
+ }
+
+ if(hhrtim->State == HAL_HRTIM_STATE_ERROR)
+ {
+ return (uint32_t)HAL_ERROR;
+ }
+
+ return delayed_protection_status;
+}
+
+/**
+ * @brief Return the actual status (active or inactive) of the burst mode controller
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval Burst mode controller status
+ */
+uint32_t HAL_HRTIM_GetBurstStatus(HRTIM_HandleTypeDef * hhrtim)
+{
+ uint32_t burst_mode_status;
+
+ /* Read burst mode status */
+ burst_mode_status = (hhrtim->Instance->sCommonRegs.BMCR & HRTIM_BMCR_BMSTAT);
+
+ return burst_mode_status;
+}
+
+/**
+ * @brief Indicate on which output the signal is currently active (when the
+ * push pull mode is enabled).
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval Burst mode controller status
+ */
+uint32_t HAL_HRTIM_GetCurrentPushPullStatus(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ uint32_t current_pushpull_status;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+
+ /* Read current push pull status */
+ current_pushpull_status = (hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxISR & HRTIM_TIMISR_CPPSTAT);
+
+ return current_pushpull_status;
+}
+
+
+/**
+ * @brief Indicate on which output the signal was applied, in push-pull mode,
+ balanced fault mode or delayed idle mode, when the protection was triggered.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval Idle Push Pull Status
+ */
+uint32_t HAL_HRTIM_GetIdlePushPullStatus(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ uint32_t idle_pushpull_status;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_TIMING_UNIT(TimerIdx));
+
+ /* Read current push pull status */
+ idle_pushpull_status = (hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxISR & HRTIM_TIMISR_IPPSTAT);
+
+ return idle_pushpull_status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HRTIM_Exported_Functions_Group10 Interrupts handling
+ * @brief Functions called when HRTIM generates an interrupt
+ * 7 interrupts can be generated by the master timer:
+ * - Master timer registers update
+ * - Synchronization event received
+ * - Master timer repetition event
+ * - Master Compare 1 to 4 event
+ * 14 interrupts can be generated by each timing unit:
+ * - Delayed protection triggered
+ * - Counter reset or roll-over event
+ * - Output 1 and output 2 reset (transition active to inactive)
+ * - Output 1 and output 2 set (transition inactive to active)
+ * - Capture 1 and 2 events
+ * - Timing unit registers update
+ * - Repetition event
+ * - Compare 1 to 4 event
+ * 7 global interrupts are generated for the whole HRTIM:
+ * - System fault and Fault 1 to 5 (regardless of the timing unit attribution)
+ * - Burst mode period completed
+@verbatim
+ ===============================================================================
+ ##### HRTIM interrupts handling #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the HRTIM
+ interrupts:
+ (+) HRTIM interrupt handler
+ (+) Callback function called when Fault1 interrupt occurs
+ (+) Callback function called when Fault2 interrupt occurs
+ (+) Callback function called when Fault3 interrupt occurs
+ (+) Callback function called when Fault4 interrupt occurs
+ (+) Callback function called when Fault5 interrupt occurs
+ (+) Callback function called when system Fault interrupt occurs
+ (+) Callback function called when burst mode period interrupt occurs
+ (+) Callback function called when synchronization input interrupt occurs
+ (+) Callback function called when a timer register update interrupt occurs
+ (+) Callback function called when a timer repetition interrupt occurs
+ (+) Callback function called when a compare 1 match interrupt occurs
+ (+) Callback function called when a compare 2 match interrupt occurs
+ (+) Callback function called when a compare 3 match interrupt occurs
+ (+) Callback function called when a compare 4 match interrupt occurs
+ (+) Callback function called when a capture 1 interrupt occurs
+ (+) Callback function called when a capture 2 interrupt occurs
+ (+) Callback function called when a delayed protection interrupt occurs
+ (+) Callback function called when a timer counter reset interrupt occurs
+ (+) Callback function called when a timer output 1 set interrupt occurs
+ (+) Callback function called when a timer output 1 reset interrupt occurs
+ (+) Callback function called when a timer output 2 set interrupt occurs
+ (+) Callback function called when a timer output 2 reset interrupt occurs
+ (+) Callback function called when a timer output 2 reset interrupt occurs
+ (+) Callback function called upon completion of a burst DMA transfer
+ (+) HRTIM callback function registration
+ (+) HRTIM callback function unregistration
+ (+) HRTIM Timer x callback function registration
+ (+) HRTIM Timer x callback function unregistration
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function handles HRTIM interrupt request.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be any value of HRTIM_Timer_Index
+ * @retval None
+ */
+void HAL_HRTIM_IRQHandler(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* HRTIM interrupts handling */
+ if (TimerIdx == HRTIM_TIMERINDEX_COMMON)
+ {
+ HRTIM_HRTIM_ISR(hhrtim);
+ }
+ else if (TimerIdx == HRTIM_TIMERINDEX_MASTER)
+ {
+ /* Master related interrupts handling */
+ HRTIM_Master_ISR(hhrtim);
+ }
+ else
+ {
+ /* Timing unit related interrupts handling */
+ HRTIM_Timer_ISR(hhrtim, TimerIdx);
+ }
+
+}
+
+/**
+ * @brief Callback function invoked when a fault 1 interrupt occurred
+ * @param hhrtim pointer to HAL HRTIM handle * @retval None
+ * @retval None
+ */
+__weak void HAL_HRTIM_Fault1Callback(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Fault1Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when a fault 2 interrupt occurred
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_Fault2Callback(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Fault2Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when a fault 3 interrupt occurred
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_Fault3Callback(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Fault3Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when a fault 4 interrupt occurred
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_Fault4Callback(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Fault4Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when a fault 5 interrupt occurred
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_Fault5Callback(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Fault5Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when a system fault interrupt occurred
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_SystemFaultCallback(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_SystemFaultCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the end of the burst mode period is reached
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_BurstModePeriodCallback(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_BurstModeCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when a synchronization input event is received
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_SynchronizationEventCallback(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_SynchronizationEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when timer registers are updated
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_RegistersUpdateCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Master_RegistersUpdateCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when timer repetition period has elapsed
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_RepetitionEventCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Master_RepetitionEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer counter matches the value
+ * programmed in the compare 1 register
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_Compare1EventCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Master_Compare1EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer counter matches the value
+ * programmed in the compare 2 register
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ */
+__weak void HAL_HRTIM_Compare2EventCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Master_Compare2EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer counter matches the value
+ * programmed in the compare 3 register
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_Compare3EventCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Master_Compare3EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer counter matches the value
+ * programmed in the compare 4 register.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_Compare4EventCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Master_Compare4EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer x capture 1 event occurs
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_Capture1EventCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Timer_Capture1EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer x capture 2 event occurs
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_Capture2EventCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Timer_Capture2EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the delayed idle or balanced idle mode is
+ * entered.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_DelayedProtectionCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Timer_DelayedProtectionCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer x counter reset/roll-over
+ * event occurs.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_CounterResetCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Timer_CounterResetCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer x output 1 is set
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_Output1SetCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Timer_Output1SetCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer x output 1 is reset
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_Output1ResetCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Timer_Output1ResetCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer x output 2 is set
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_Output2SetCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Timer_Output2SetCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when the timer x output 2 is reset
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_Output2ResetCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_Timer_Output2ResetCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when a DMA burst transfer is completed
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_MASTER for master timer
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+ */
+__weak void HAL_HRTIM_BurstDMATransferCallback(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+ UNUSED(TimerIdx);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_BurstDMATransferCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Callback function invoked when a DMA error occurs
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+__weak void HAL_HRTIM_ErrorCallback(HRTIM_HandleTypeDef *hhrtim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hhrtim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HRTIM_ErrorCallback could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief HRTIM callback function registration
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param CallbackID ID of the HRTIM callback function to register
+ * This parameter can be one of the following values:
+ * @arg HAL_HRTIM_FAULT1CALLBACK_CB_ID
+ * @arg HAL_HRTIM_FAULT2CALLBACK_CB_ID
+ * @arg HAL_HRTIM_FAULT3CALLBACK_CB_ID
+ * @arg HAL_HRTIM_FAULT4CALLBACK_CB_ID
+ * @arg HAL_HRTIM_FAULT5CALLBACK_CB_ID
+ * @arg HAL_HRTIM_SYSTEMFAULTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_BURSTMODEPERIODCALLBACK_CB_ID
+ * @arg HAL_HRTIM_SYNCHRONIZATIONEVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_ERRORCALLBACK_CB_ID
+ * @arg HAL_HRTIM_MSPINIT_CB_ID
+ * @arg HAL_HRTIM_MSPDEINIT_CB_ID
+ * @param pCallback Callback function pointer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_RegisterCallback(HRTIM_HandleTypeDef * hhrtim,
+ HAL_HRTIM_CallbackIDTypeDef CallbackID,
+ pHRTIM_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hhrtim);
+
+ if (HAL_HRTIM_STATE_READY == hhrtim->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HRTIM_FAULT1CALLBACK_CB_ID :
+ hhrtim->Fault1Callback = pCallback;
+ break;
+
+ case HAL_HRTIM_FAULT2CALLBACK_CB_ID :
+ hhrtim->Fault2Callback = pCallback;
+ break;
+
+ case HAL_HRTIM_FAULT3CALLBACK_CB_ID :
+ hhrtim->Fault3Callback = pCallback;
+ break;
+
+ case HAL_HRTIM_FAULT4CALLBACK_CB_ID :
+ hhrtim->Fault4Callback = pCallback;
+ break;
+
+ case HAL_HRTIM_FAULT5CALLBACK_CB_ID :
+ hhrtim->Fault5Callback = pCallback;
+ break;
+
+ case HAL_HRTIM_SYSTEMFAULTCALLBACK_CB_ID :
+ hhrtim->SystemFaultCallback = pCallback;
+ break;
+
+
+ case HAL_HRTIM_BURSTMODEPERIODCALLBACK_CB_ID :
+ hhrtim->BurstModePeriodCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_SYNCHRONIZATIONEVENTCALLBACK_CB_ID :
+ hhrtim->SynchronizationEventCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_ERRORCALLBACK_CB_ID :
+ hhrtim->ErrorCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_MSPINIT_CB_ID :
+ hhrtim->MspInitCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_MSPDEINIT_CB_ID :
+ hhrtim->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_HRTIM_STATE_RESET == hhrtim->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HRTIM_MSPINIT_CB_ID :
+ hhrtim->MspInitCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_MSPDEINIT_CB_ID :
+ hhrtim->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhrtim);
+
+ return status;
+}
+
+/**
+ * @brief HRTIM callback function un-registration
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param CallbackID ID of the HRTIM callback function to unregister
+ * This parameter can be one of the following values:
+ * @arg HAL_HRTIM_FAULT1CALLBACK_CB_ID
+ * @arg HAL_HRTIM_FAULT2CALLBACK_CB_ID
+ * @arg HAL_HRTIM_FAULT3CALLBACK_CB_ID
+ * @arg HAL_HRTIM_FAULT4CALLBACK_CB_ID
+ * @arg HAL_HRTIM_FAULT5CALLBACK_CB_ID
+ * @arg HAL_HRTIM_SYSTEMFAULTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_BURSTMODEPERIODCALLBACK_CB_ID
+ * @arg HAL_HRTIM_SYNCHRONIZATIONEVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_ERRORCALLBACK_CB_ID
+ * @arg HAL_HRTIM_MSPINIT_CB_ID
+ * @arg HAL_HRTIM_MSPDEINIT_CB_ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_UnRegisterCallback(HRTIM_HandleTypeDef * hhrtim,
+ HAL_HRTIM_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hhrtim);
+
+ if (HAL_HRTIM_STATE_READY == hhrtim->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HRTIM_FAULT1CALLBACK_CB_ID :
+ hhrtim->Fault1Callback = HAL_HRTIM_Fault1Callback;
+ break;
+
+ case HAL_HRTIM_FAULT2CALLBACK_CB_ID :
+ hhrtim->Fault2Callback = HAL_HRTIM_Fault2Callback;
+ break;
+
+ case HAL_HRTIM_FAULT3CALLBACK_CB_ID :
+ hhrtim->Fault3Callback = HAL_HRTIM_Fault3Callback;
+ break;
+
+ case HAL_HRTIM_FAULT4CALLBACK_CB_ID :
+ hhrtim->Fault4Callback = HAL_HRTIM_Fault4Callback;
+ break;
+
+ case HAL_HRTIM_FAULT5CALLBACK_CB_ID :
+ hhrtim->Fault5Callback = HAL_HRTIM_Fault5Callback;
+ break;
+
+ case HAL_HRTIM_SYSTEMFAULTCALLBACK_CB_ID :
+ hhrtim->SystemFaultCallback = HAL_HRTIM_SystemFaultCallback;
+ break;
+
+
+ case HAL_HRTIM_BURSTMODEPERIODCALLBACK_CB_ID :
+ hhrtim->BurstModePeriodCallback = HAL_HRTIM_BurstModePeriodCallback;
+ break;
+
+ case HAL_HRTIM_SYNCHRONIZATIONEVENTCALLBACK_CB_ID :
+ hhrtim->SynchronizationEventCallback = HAL_HRTIM_SynchronizationEventCallback;
+ break;
+
+ case HAL_HRTIM_ERRORCALLBACK_CB_ID :
+ hhrtim->ErrorCallback = HAL_HRTIM_ErrorCallback;
+ break;
+
+ case HAL_HRTIM_MSPINIT_CB_ID :
+ hhrtim->MspInitCallback = HAL_HRTIM_MspInit;
+ break;
+
+ case HAL_HRTIM_MSPDEINIT_CB_ID :
+ hhrtim->MspDeInitCallback = HAL_HRTIM_MspDeInit;
+ break;
+
+ default :
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_HRTIM_STATE_RESET == hhrtim->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HRTIM_MSPINIT_CB_ID :
+ hhrtim->MspInitCallback = HAL_HRTIM_MspInit;
+ break;
+
+ case HAL_HRTIM_MSPDEINIT_CB_ID :
+ hhrtim->MspDeInitCallback = HAL_HRTIM_MspDeInit;
+ break;
+
+ default :
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhrtim);
+
+ return status;
+}
+
+/**
+ * @brief HRTIM Timer x callback function registration
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param CallbackID ID of the HRTIM Timer x callback function to register
+ * This parameter can be one of the following values:
+ * @arg HAL_HRTIM_REGISTERSUPDATECALLBACK_CB_ID
+ * @arg HAL_HRTIM_REPETITIONEVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COMPARE1EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COMPARE2EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COMPARE3EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COMPARE4EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_CAPTURE1EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_CAPTURE2EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_DELAYEDPROTECTIONCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COUNTERRESETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_OUTPUT1SETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_OUTPUT1RESETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_OUTPUT2SETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_OUTPUT2RESETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_BURSTDMATRANSFERCALLBACK_CB_ID
+ * @param pCallback Callback function pointer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_TIMxRegisterCallback(HRTIM_HandleTypeDef * hhrtim,
+ HAL_HRTIM_CallbackIDTypeDef CallbackID,
+ pHRTIM_TIMxCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hhrtim);
+
+ if (HAL_HRTIM_STATE_READY == hhrtim->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HRTIM_REGISTERSUPDATECALLBACK_CB_ID :
+ hhrtim->RegistersUpdateCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_REPETITIONEVENTCALLBACK_CB_ID :
+ hhrtim->RepetitionEventCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_COMPARE1EVENTCALLBACK_CB_ID :
+ hhrtim->Compare1EventCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_COMPARE2EVENTCALLBACK_CB_ID :
+ hhrtim->Compare2EventCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_COMPARE3EVENTCALLBACK_CB_ID :
+ hhrtim->Compare3EventCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_COMPARE4EVENTCALLBACK_CB_ID :
+ hhrtim->Compare4EventCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_CAPTURE1EVENTCALLBACK_CB_ID :
+ hhrtim->Capture1EventCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_CAPTURE2EVENTCALLBACK_CB_ID :
+ hhrtim->Capture2EventCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_DELAYEDPROTECTIONCALLBACK_CB_ID :
+ hhrtim->DelayedProtectionCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_COUNTERRESETCALLBACK_CB_ID :
+ hhrtim->CounterResetCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_OUTPUT1SETCALLBACK_CB_ID :
+ hhrtim->Output1SetCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_OUTPUT1RESETCALLBACK_CB_ID :
+ hhrtim->Output1ResetCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_OUTPUT2SETCALLBACK_CB_ID :
+ hhrtim->Output2SetCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_OUTPUT2RESETCALLBACK_CB_ID :
+ hhrtim->Output2ResetCallback = pCallback;
+ break;
+
+ case HAL_HRTIM_BURSTDMATRANSFERCALLBACK_CB_ID :
+ hhrtim->BurstDMATransferCallback = pCallback;
+ break;
+
+ default :
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhrtim);
+
+ return status;
+}
+
+/**
+ * @brief HRTIM Timer x callback function un-registration
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param CallbackID ID of the HRTIM callback Timer x function to unregister
+ * This parameter can be one of the following values:
+ * @arg HAL_HRTIM_REGISTERSUPDATECALLBACK_CB_ID
+ * @arg HAL_HRTIM_REPETITIONEVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COMPARE1EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COMPARE2EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COMPARE3EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COMPARE4EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_CAPTURE1EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_CAPTURE2EVENTCALLBACK_CB_ID
+ * @arg HAL_HRTIM_DELAYEDPROTECTIONCALLBACK_CB_ID
+ * @arg HAL_HRTIM_COUNTERRESETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_OUTPUT1SETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_OUTPUT1RESETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_OUTPUT2SETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_OUTPUT2RESETCALLBACK_CB_ID
+ * @arg HAL_HRTIM_BURSTDMATRANSFERCALLBACK_CB_ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HRTIM_TIMxUnRegisterCallback(HRTIM_HandleTypeDef * hhrtim,
+ HAL_HRTIM_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hhrtim);
+
+ if (HAL_HRTIM_STATE_READY == hhrtim->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_HRTIM_REGISTERSUPDATECALLBACK_CB_ID :
+ hhrtim->RegistersUpdateCallback = HAL_HRTIM_RegistersUpdateCallback;
+ break;
+
+ case HAL_HRTIM_REPETITIONEVENTCALLBACK_CB_ID :
+ hhrtim->RepetitionEventCallback = HAL_HRTIM_RepetitionEventCallback;
+ break;
+
+ case HAL_HRTIM_COMPARE1EVENTCALLBACK_CB_ID :
+ hhrtim->Compare1EventCallback = HAL_HRTIM_Compare1EventCallback;
+ break;
+
+ case HAL_HRTIM_COMPARE2EVENTCALLBACK_CB_ID :
+ hhrtim->Compare2EventCallback = HAL_HRTIM_Compare2EventCallback;
+ break;
+
+ case HAL_HRTIM_COMPARE3EVENTCALLBACK_CB_ID :
+ hhrtim->Compare3EventCallback = HAL_HRTIM_Compare3EventCallback;
+ break;
+
+ case HAL_HRTIM_COMPARE4EVENTCALLBACK_CB_ID :
+ hhrtim->Compare4EventCallback = HAL_HRTIM_Compare4EventCallback;
+ break;
+
+ case HAL_HRTIM_CAPTURE1EVENTCALLBACK_CB_ID :
+ hhrtim->Capture1EventCallback = HAL_HRTIM_Capture1EventCallback;
+ break;
+
+ case HAL_HRTIM_CAPTURE2EVENTCALLBACK_CB_ID :
+ hhrtim->Capture2EventCallback = HAL_HRTIM_Capture2EventCallback;
+ break;
+
+ case HAL_HRTIM_DELAYEDPROTECTIONCALLBACK_CB_ID :
+ hhrtim->DelayedProtectionCallback = HAL_HRTIM_DelayedProtectionCallback;
+ break;
+
+ case HAL_HRTIM_COUNTERRESETCALLBACK_CB_ID :
+ hhrtim->CounterResetCallback = HAL_HRTIM_CounterResetCallback;
+ break;
+
+ case HAL_HRTIM_OUTPUT1SETCALLBACK_CB_ID :
+ hhrtim->Output1SetCallback = HAL_HRTIM_Output1SetCallback;
+ break;
+
+ case HAL_HRTIM_OUTPUT1RESETCALLBACK_CB_ID :
+ hhrtim->Output1ResetCallback = HAL_HRTIM_Output1ResetCallback;
+ break;
+
+ case HAL_HRTIM_OUTPUT2SETCALLBACK_CB_ID :
+ hhrtim->Output2SetCallback = HAL_HRTIM_Output2SetCallback;
+ break;
+
+ case HAL_HRTIM_OUTPUT2RESETCALLBACK_CB_ID :
+ hhrtim->Output2ResetCallback = HAL_HRTIM_Output2ResetCallback;
+ break;
+
+ case HAL_HRTIM_BURSTDMATRANSFERCALLBACK_CB_ID :
+ hhrtim->BurstDMATransferCallback = HAL_HRTIM_BurstDMATransferCallback;
+ break;
+
+ default :
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the state */
+ hhrtim->State = HAL_HRTIM_STATE_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hhrtim);
+
+ return status;
+}
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup HRTIM_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Configure the master timer time base
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param pTimeBaseCfg pointer to the time base configuration structure
+ * @retval None
+ */
+static void HRTIM_MasterBase_Config(HRTIM_HandleTypeDef * hhrtim,
+ HRTIM_TimeBaseCfgTypeDef * pTimeBaseCfg)
+{
+ uint32_t hrtim_mcr;
+
+ /* Configure master timer */
+ hrtim_mcr = hhrtim->Instance->sMasterRegs.MCR;
+
+ /* Set the prescaler ratio */
+ hrtim_mcr &= (uint32_t) ~(HRTIM_MCR_CK_PSC);
+ hrtim_mcr |= (uint32_t)pTimeBaseCfg->PrescalerRatio;
+
+ /* Set the operating mode */
+ hrtim_mcr &= (uint32_t) ~(HRTIM_MCR_CONT | HRTIM_MCR_RETRIG);
+ hrtim_mcr |= (uint32_t)pTimeBaseCfg->Mode;
+
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sMasterRegs.MCR = hrtim_mcr;
+ hhrtim->Instance->sMasterRegs.MPER = pTimeBaseCfg->Period;
+ hhrtim->Instance->sMasterRegs.MREP = pTimeBaseCfg->RepetitionCounter;
+}
+
+/**
+ * @brief Configure timing unit (Timer A to Timer E) time base
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * @param pTimeBaseCfg pointer to the time base configuration structure
+ * @retval None
+ */
+static void HRTIM_TimingUnitBase_Config(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx ,
+ HRTIM_TimeBaseCfgTypeDef * pTimeBaseCfg)
+{
+ uint32_t hrtim_timcr;
+
+ /* Configure master timing unit */
+ hrtim_timcr = hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR;
+
+ /* Set the prescaler ratio */
+ hrtim_timcr &= (uint32_t) ~(HRTIM_TIMCR_CK_PSC);
+ hrtim_timcr |= (uint32_t)pTimeBaseCfg->PrescalerRatio;
+
+ /* Set the operating mode */
+ hrtim_timcr &= (uint32_t) ~(HRTIM_TIMCR_CONT | HRTIM_TIMCR_RETRIG);
+ hrtim_timcr |= (uint32_t)pTimeBaseCfg->Mode;
+
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR = hrtim_timcr;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].PERxR = pTimeBaseCfg->Period;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].REPxR = pTimeBaseCfg->RepetitionCounter;
+}
+
+/**
+ * @brief Configure the master timer in waveform mode
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param pTimerCfg pointer to the timer configuration data structure
+ * @retval None
+ */
+static void HRTIM_MasterWaveform_Config(HRTIM_HandleTypeDef * hhrtim,
+ HRTIM_TimerCfgTypeDef * pTimerCfg)
+{
+ uint32_t hrtim_mcr;
+ uint32_t hrtim_bmcr;
+
+ /* Configure master timer */
+ hrtim_mcr = hhrtim->Instance->sMasterRegs.MCR;
+ hrtim_bmcr = hhrtim->Instance->sCommonRegs.BMCR;
+
+ /* Enable/Disable the half mode */
+ hrtim_mcr &= ~(HRTIM_MCR_HALF);
+ hrtim_mcr |= pTimerCfg->HalfModeEnable;
+
+ /* Enable/Disable the timer start upon synchronization event reception */
+ hrtim_mcr &= ~(HRTIM_MCR_SYNCSTRTM);
+ hrtim_mcr |= pTimerCfg->StartOnSync;
+
+ /* Enable/Disable the timer reset upon synchronization event reception */
+ hrtim_mcr &= ~(HRTIM_MCR_SYNCRSTM);
+ hrtim_mcr |= pTimerCfg->ResetOnSync;
+
+ /* Enable/Disable the DAC synchronization event generation */
+ hrtim_mcr &= ~(HRTIM_MCR_DACSYNC);
+ hrtim_mcr |= pTimerCfg->DACSynchro;
+
+ /* Enable/Disable preload meachanism for timer registers */
+ hrtim_mcr &= ~(HRTIM_MCR_PREEN);
+ hrtim_mcr |= pTimerCfg->PreloadEnable;
+
+ /* Master timer registers update handling */
+ hrtim_mcr &= ~(HRTIM_MCR_BRSTDMA);
+ hrtim_mcr |= (pTimerCfg->UpdateGating << 2U);
+
+ /* Enable/Disable registers update on repetition */
+ hrtim_mcr &= ~(HRTIM_MCR_MREPU);
+ hrtim_mcr |= pTimerCfg->RepetitionUpdate;
+
+ /* Set the timer burst mode */
+ hrtim_bmcr &= ~(HRTIM_BMCR_MTBM);
+ hrtim_bmcr |= pTimerCfg->BurstMode;
+
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sMasterRegs.MCR = hrtim_mcr;
+ hhrtim->Instance->sCommonRegs.BMCR = hrtim_bmcr;
+}
+
+/**
+ * @brief Configure timing unit (Timer A to Timer E) in waveform mode
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * @param pTimerCfg pointer to the timer configuration data structure
+ * @retval None
+ */
+static void HRTIM_TimingUnitWaveform_Config(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ HRTIM_TimerCfgTypeDef * pTimerCfg)
+{
+ uint32_t hrtim_timcr;
+ uint32_t hrtim_timfltr;
+ uint32_t hrtim_timoutr;
+ uint32_t hrtim_timrstr;
+ uint32_t hrtim_bmcr;
+
+ /* UPDGAT bitfield must be reset before programming a new value */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR &= ~(HRTIM_TIMCR_UPDGAT);
+
+ /* Configure timing unit (Timer A to Timer E) */
+ hrtim_timcr = hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR;
+ hrtim_timfltr = hhrtim->Instance->sTimerxRegs[TimerIdx].FLTxR;
+ hrtim_timoutr = hhrtim->Instance->sTimerxRegs[TimerIdx].OUTxR;
+ hrtim_bmcr = hhrtim->Instance->sCommonRegs.BMCR;
+
+ /* Enable/Disable the half mode */
+ hrtim_timcr &= ~(HRTIM_TIMCR_HALF);
+ hrtim_timcr |= pTimerCfg->HalfModeEnable;
+
+ /* Enable/Disable the timer start upon synchronization event reception */
+ hrtim_timcr &= ~(HRTIM_TIMCR_SYNCSTRT);
+ hrtim_timcr |= pTimerCfg->StartOnSync;
+
+ /* Enable/Disable the timer reset upon synchronization event reception */
+ hrtim_timcr &= ~(HRTIM_TIMCR_SYNCRST);
+ hrtim_timcr |= pTimerCfg->ResetOnSync;
+
+ /* Enable/Disable the DAC synchronization event generation */
+ hrtim_timcr &= ~(HRTIM_TIMCR_DACSYNC);
+ hrtim_timcr |= pTimerCfg->DACSynchro;
+
+ /* Enable/Disable preload meachanism for timer registers */
+ hrtim_timcr &= ~(HRTIM_TIMCR_PREEN);
+ hrtim_timcr |= pTimerCfg->PreloadEnable;
+
+ /* Timing unit registers update handling */
+ hrtim_timcr &= ~(HRTIM_TIMCR_UPDGAT);
+ hrtim_timcr |= pTimerCfg->UpdateGating;
+
+ /* Enable/Disable registers update on repetition */
+ hrtim_timcr &= ~(HRTIM_TIMCR_TREPU);
+ if (pTimerCfg->RepetitionUpdate == HRTIM_UPDATEONREPETITION_ENABLED)
+ {
+ hrtim_timcr |= HRTIM_TIMCR_TREPU;
+ }
+
+ /* Set the push-pull mode */
+ hrtim_timcr &= ~(HRTIM_TIMCR_PSHPLL);
+ hrtim_timcr |= pTimerCfg->PushPull;
+
+ /* Enable/Disable registers update on timer counter reset */
+ hrtim_timcr &= ~(HRTIM_TIMCR_TRSTU);
+ hrtim_timcr |= pTimerCfg->ResetUpdate;
+
+ /* Set the timer update trigger */
+ hrtim_timcr &= ~(HRTIM_TIMCR_TIMUPDATETRIGGER);
+ hrtim_timcr |= pTimerCfg->UpdateTrigger;
+
+ /* Enable/Disable the fault channel at timer level */
+ hrtim_timfltr &= ~(HRTIM_FLTR_FLTxEN);
+ hrtim_timfltr |= (pTimerCfg->FaultEnable & HRTIM_FLTR_FLTxEN);
+
+ /* Lock/Unlock fault sources at timer level */
+ hrtim_timfltr &= ~(HRTIM_FLTR_FLTLCK);
+ hrtim_timfltr |= pTimerCfg->FaultLock;
+
+ /* The deadtime cannot be used simultaneously with the push-pull mode */
+ if (pTimerCfg->PushPull == HRTIM_TIMPUSHPULLMODE_DISABLED)
+ {
+ /* Enable/Disable dead time insertion at timer level */
+ hrtim_timoutr &= ~(HRTIM_OUTR_DTEN);
+ hrtim_timoutr |= pTimerCfg->DeadTimeInsertion;
+ }
+
+ /* Enable/Disable delayed protection at timer level
+ Delayed Idle is available whatever the timer operating mode (regular, push-pull)
+ Balanced Idle is only available in push-pull mode
+ */
+ if ( ((pTimerCfg->DelayedProtectionMode != HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_BALANCED_EEV6)
+ && (pTimerCfg->DelayedProtectionMode != HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_BALANCED_EEV7))
+ || (pTimerCfg->PushPull == HRTIM_TIMPUSHPULLMODE_ENABLED))
+ {
+ hrtim_timoutr &= ~(HRTIM_OUTR_DLYPRT| HRTIM_OUTR_DLYPRTEN);
+ hrtim_timoutr |= pTimerCfg->DelayedProtectionMode;
+ }
+
+ /* Set the timer counter reset trigger */
+ hrtim_timrstr = pTimerCfg->ResetTrigger;
+
+ /* Set the timer burst mode */
+ switch (TimerIdx)
+ {
+ case HRTIM_TIMERINDEX_TIMER_A:
+ {
+ hrtim_bmcr &= ~(HRTIM_BMCR_TABM);
+ hrtim_bmcr |= ( pTimerCfg->BurstMode << 1U);
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_B:
+ {
+ hrtim_bmcr &= ~(HRTIM_BMCR_TBBM);
+ hrtim_bmcr |= ( pTimerCfg->BurstMode << 2U);
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_C:
+ {
+ hrtim_bmcr &= ~(HRTIM_BMCR_TCBM);
+ hrtim_bmcr |= ( pTimerCfg->BurstMode << 3U);
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_D:
+ {
+ hrtim_bmcr &= ~(HRTIM_BMCR_TDBM);
+ hrtim_bmcr |= ( pTimerCfg->BurstMode << 4U);
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_E:
+ {
+ hrtim_bmcr &= ~(HRTIM_BMCR_TEBM);
+ hrtim_bmcr |= ( pTimerCfg->BurstMode << 5U);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].TIMxCR = hrtim_timcr;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].FLTxR = hrtim_timfltr;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].OUTxR = hrtim_timoutr;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = hrtim_timrstr;
+ hhrtim->Instance->sCommonRegs.BMCR = hrtim_bmcr;
+}
+
+/**
+ * @brief Configure a capture unit
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * @param CaptureUnit Capture unit identifier
+ * @param Event Event reference
+ * @retval None
+ */
+static void HRTIM_CaptureUnitConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t CaptureUnit,
+ uint32_t Event)
+{
+ uint32_t CaptureTrigger = 0xFFFFFFFFU;
+
+ switch (Event)
+ {
+ case HRTIM_EVENT_1:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_1;
+ break;
+ }
+
+ case HRTIM_EVENT_2:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_2;
+ break;
+ }
+
+ case HRTIM_EVENT_3:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_3;
+ break;
+ }
+
+ case HRTIM_EVENT_4:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_4;
+ break;
+ }
+
+ case HRTIM_EVENT_5:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_5;
+ break;
+ }
+
+ case HRTIM_EVENT_6:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_6;
+ break;
+ }
+
+ case HRTIM_EVENT_7:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_7;
+ break;
+ }
+
+ case HRTIM_EVENT_8:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_8;
+ break;
+ }
+
+ case HRTIM_EVENT_9:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_9;
+ break;
+ }
+
+ case HRTIM_EVENT_10:
+ {
+ CaptureTrigger = HRTIM_CAPTURETRIGGER_EEV_10;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ switch (CaptureUnit)
+ {
+ case HRTIM_CAPTUREUNIT_1:
+ {
+ hhrtim->TimerParam[TimerIdx].CaptureTrigger1 = CaptureTrigger;
+ break;
+ }
+
+ case HRTIM_CAPTUREUNIT_2:
+ {
+ hhrtim->TimerParam[TimerIdx].CaptureTrigger2 = CaptureTrigger;
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief Configure the output of a timing unit
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * @param Output timing unit output identifier
+ * @param pOutputCfg pointer to the output configuration data structure
+ * @retval None
+ */
+static void HRTIM_OutputConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Output,
+ HRTIM_OutputCfgTypeDef * pOutputCfg)
+{
+ uint32_t hrtim_outr;
+ uint32_t hrtim_dtr;
+
+ uint32_t shift = 0U;
+
+ hrtim_outr = hhrtim->Instance->sTimerxRegs[TimerIdx].OUTxR;
+ hrtim_dtr = hhrtim->Instance->sTimerxRegs[TimerIdx].DTxR;
+
+ switch (Output)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ /* Set the output set/reset crossbar */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].SETx1R = pOutputCfg->SetSource;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTx1R = pOutputCfg->ResetSource;
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ /* Set the output set/reset crossbar */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].SETx2R = pOutputCfg->SetSource;
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTx2R = pOutputCfg->ResetSource;
+ shift = 16U;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Clear output config */
+ hrtim_outr &= ~((HRTIM_OUTR_POL1 |
+ HRTIM_OUTR_IDLM1 |
+ HRTIM_OUTR_IDLES1|
+ HRTIM_OUTR_FAULT1|
+ HRTIM_OUTR_CHP1 |
+ HRTIM_OUTR_DIDL1) << shift);
+
+ /* Set the polarity */
+ hrtim_outr |= (pOutputCfg->Polarity << shift);
+
+ /* Set the IDLE mode */
+ hrtim_outr |= (pOutputCfg->IdleMode << shift);
+
+ /* Set the IDLE state */
+ hrtim_outr |= (pOutputCfg->IdleLevel << shift);
+
+ /* Set the FAULT state */
+ hrtim_outr |= (pOutputCfg->FaultLevel << shift);
+
+ /* Set the chopper mode */
+ hrtim_outr |= (pOutputCfg->ChopperModeEnable << shift);
+
+ /* Set the burst mode entry mode : deadtime insertion when entering the idle
+ state during a burst mode operation is allowed only under the following
+ conditions:
+ - the outputs is active during the burst mode (IDLES=1U)
+ - positive deadtimes (SDTR/SDTF set to 0U)
+ */
+ if ((pOutputCfg->IdleLevel == HRTIM_OUTPUTIDLELEVEL_ACTIVE) &&
+ ((hrtim_dtr & HRTIM_DTR_SDTR) == (uint32_t)RESET) &&
+ ((hrtim_dtr & HRTIM_DTR_SDTF) == (uint32_t)RESET))
+ {
+ hrtim_outr |= (pOutputCfg->BurstModeEntryDelayed << shift);
+ }
+
+ /* Update HRTIM register */
+ hhrtim->Instance->sTimerxRegs[TimerIdx].OUTxR = hrtim_outr;
+}
+
+/**
+ * @brief Configure an external event channel
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param Event Event channel identifier
+ * @param pEventCfg pointer to the event channel configuration data structure
+ * @retval None
+ */
+static void HRTIM_EventConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t Event,
+ HRTIM_EventCfgTypeDef *pEventCfg)
+{
+ uint32_t hrtim_eecr1;
+ uint32_t hrtim_eecr2;
+ uint32_t hrtim_eecr3;
+
+ /* Configure external event channel */
+ hrtim_eecr1 = hhrtim->Instance->sCommonRegs.EECR1;
+ hrtim_eecr2 = hhrtim->Instance->sCommonRegs.EECR2;
+ hrtim_eecr3 = hhrtim->Instance->sCommonRegs.EECR3;
+
+ switch (Event)
+ {
+ case HRTIM_EVENT_NONE:
+ {
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sCommonRegs.EECR1 = 0U;
+ hhrtim->Instance->sCommonRegs.EECR2 = 0U;
+ hhrtim->Instance->sCommonRegs.EECR3 = 0U;
+ break;
+ }
+
+ case HRTIM_EVENT_1:
+ {
+ hrtim_eecr1 &= ~(HRTIM_EECR1_EE1SRC | HRTIM_EECR1_EE1POL | HRTIM_EECR1_EE1SNS | HRTIM_EECR1_EE1FAST);
+ hrtim_eecr1 |= (pEventCfg->Source & HRTIM_EECR1_EE1SRC);
+ hrtim_eecr1 |= (pEventCfg->Polarity & HRTIM_EECR1_EE1POL);
+ hrtim_eecr1 |= (pEventCfg->Sensitivity & HRTIM_EECR1_EE1SNS);
+ /* Update the HRTIM registers (all bitfields but EE1FAST bit) */
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ /* Update the HRTIM registers (EE1FAST bit) */
+ hrtim_eecr1 |= (pEventCfg->FastMode & HRTIM_EECR1_EE1FAST);
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ break;
+ }
+
+ case HRTIM_EVENT_2:
+ {
+ hrtim_eecr1 &= ~(HRTIM_EECR1_EE2SRC | HRTIM_EECR1_EE2POL | HRTIM_EECR1_EE2SNS | HRTIM_EECR1_EE2FAST);
+ hrtim_eecr1 |= ((pEventCfg->Source << 6U) & HRTIM_EECR1_EE2SRC);
+ hrtim_eecr1 |= ((pEventCfg->Polarity << 6U) & HRTIM_EECR1_EE2POL);
+ hrtim_eecr1 |= ((pEventCfg->Sensitivity << 6U) & HRTIM_EECR1_EE2SNS);
+ /* Update the HRTIM registers (all bitfields but EE2FAST bit) */
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ /* Update the HRTIM registers (EE2FAST bit) */
+ hrtim_eecr1 |= ((pEventCfg->FastMode << 6U) & HRTIM_EECR1_EE2FAST);
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ break;
+ }
+
+ case HRTIM_EVENT_3:
+ {
+ hrtim_eecr1 &= ~(HRTIM_EECR1_EE3SRC | HRTIM_EECR1_EE3POL | HRTIM_EECR1_EE3SNS | HRTIM_EECR1_EE3FAST);
+ hrtim_eecr1 |= ((pEventCfg->Source << 12U) & HRTIM_EECR1_EE3SRC);
+ hrtim_eecr1 |= ((pEventCfg->Polarity << 12U) & HRTIM_EECR1_EE3POL);
+ hrtim_eecr1 |= ((pEventCfg->Sensitivity << 12U) & HRTIM_EECR1_EE3SNS);
+ /* Update the HRTIM registers (all bitfields but EE3FAST bit) */
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ /* Update the HRTIM registers (EE3FAST bit) */
+ hrtim_eecr1 |= ((pEventCfg->FastMode << 12U) & HRTIM_EECR1_EE3FAST);
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ break;
+ }
+
+ case HRTIM_EVENT_4:
+ {
+ hrtim_eecr1 &= ~(HRTIM_EECR1_EE4SRC | HRTIM_EECR1_EE4POL | HRTIM_EECR1_EE4SNS | HRTIM_EECR1_EE4FAST);
+ hrtim_eecr1 |= ((pEventCfg->Source << 18U) & HRTIM_EECR1_EE4SRC);
+ hrtim_eecr1 |= ((pEventCfg->Polarity << 18U) & HRTIM_EECR1_EE4POL);
+ hrtim_eecr1 |= ((pEventCfg->Sensitivity << 18U) & HRTIM_EECR1_EE4SNS);
+ /* Update the HRTIM registers (all bitfields but EE4FAST bit) */
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ /* Update the HRTIM registers (EE4FAST bit) */
+ hrtim_eecr1 |= ((pEventCfg->FastMode << 18U) & HRTIM_EECR1_EE4FAST);
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ break;
+ }
+
+ case HRTIM_EVENT_5:
+ {
+ hrtim_eecr1 &= ~(HRTIM_EECR1_EE5SRC | HRTIM_EECR1_EE5POL | HRTIM_EECR1_EE5SNS | HRTIM_EECR1_EE5FAST);
+ hrtim_eecr1 |= ((pEventCfg->Source << 24U) & HRTIM_EECR1_EE5SRC);
+ hrtim_eecr1 |= ((pEventCfg->Polarity << 24U) & HRTIM_EECR1_EE5POL);
+ hrtim_eecr1 |= ((pEventCfg->Sensitivity << 24U) & HRTIM_EECR1_EE5SNS);
+ /* Update the HRTIM registers (all bitfields but EE5FAST bit) */
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ /* Update the HRTIM registers (EE5FAST bit) */
+ hrtim_eecr1 |= ((pEventCfg->FastMode << 24U) & HRTIM_EECR1_EE5FAST);
+ hhrtim->Instance->sCommonRegs.EECR1 = hrtim_eecr1;
+ break;
+ }
+
+ case HRTIM_EVENT_6:
+ {
+ hrtim_eecr2 &= ~(HRTIM_EECR2_EE6SRC | HRTIM_EECR2_EE6POL | HRTIM_EECR2_EE6SNS);
+ hrtim_eecr2 |= (pEventCfg->Source & HRTIM_EECR2_EE6SRC);
+ hrtim_eecr2 |= (pEventCfg->Polarity & HRTIM_EECR2_EE6POL);
+ hrtim_eecr2 |= (pEventCfg->Sensitivity & HRTIM_EECR2_EE6SNS);
+ hrtim_eecr3 &= ~(HRTIM_EECR3_EE6F);
+ hrtim_eecr3 |= (pEventCfg->Filter & HRTIM_EECR3_EE6F);
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sCommonRegs.EECR2 = hrtim_eecr2;
+ hhrtim->Instance->sCommonRegs.EECR3 = hrtim_eecr3;
+ break;
+ }
+
+ case HRTIM_EVENT_7:
+ {
+ hrtim_eecr2 &= ~(HRTIM_EECR2_EE7SRC | HRTIM_EECR2_EE7POL | HRTIM_EECR2_EE7SNS);
+ hrtim_eecr2 |= ((pEventCfg->Source << 6U) & HRTIM_EECR2_EE7SRC);
+ hrtim_eecr2 |= ((pEventCfg->Polarity << 6U) & HRTIM_EECR2_EE7POL);
+ hrtim_eecr2 |= ((pEventCfg->Sensitivity << 6U) & HRTIM_EECR2_EE7SNS);
+ hrtim_eecr3 &= ~(HRTIM_EECR3_EE7F);
+ hrtim_eecr3 |= ((pEventCfg->Filter << 6U) & HRTIM_EECR3_EE7F);
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sCommonRegs.EECR2 = hrtim_eecr2;
+ hhrtim->Instance->sCommonRegs.EECR3 = hrtim_eecr3;
+ break;
+ }
+
+ case HRTIM_EVENT_8:
+ {
+ hrtim_eecr2 &= ~(HRTIM_EECR2_EE8SRC | HRTIM_EECR2_EE8POL | HRTIM_EECR2_EE8SNS);
+ hrtim_eecr2 |= ((pEventCfg->Source << 12U) & HRTIM_EECR2_EE8SRC);
+ hrtim_eecr2 |= ((pEventCfg->Polarity << 12U) & HRTIM_EECR2_EE8POL);
+ hrtim_eecr2 |= ((pEventCfg->Sensitivity << 12U) & HRTIM_EECR2_EE8SNS);
+ hrtim_eecr3 &= ~(HRTIM_EECR3_EE8F);
+ hrtim_eecr3 |= ((pEventCfg->Filter << 12U) & HRTIM_EECR3_EE8F );
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sCommonRegs.EECR2 = hrtim_eecr2;
+ hhrtim->Instance->sCommonRegs.EECR3 = hrtim_eecr3;
+ break;
+ }
+
+ case HRTIM_EVENT_9:
+ {
+ hrtim_eecr2 &= ~(HRTIM_EECR2_EE9SRC | HRTIM_EECR2_EE9POL | HRTIM_EECR2_EE9SNS);
+ hrtim_eecr2 |= ((pEventCfg->Source << 18U) & HRTIM_EECR2_EE9SRC);
+ hrtim_eecr2 |= ((pEventCfg->Polarity << 18U) & HRTIM_EECR2_EE9POL);
+ hrtim_eecr2 |= ((pEventCfg->Sensitivity << 18U) & HRTIM_EECR2_EE9SNS);
+ hrtim_eecr3 &= ~(HRTIM_EECR3_EE9F);
+ hrtim_eecr3 |= ((pEventCfg->Filter << 18U) & HRTIM_EECR3_EE9F);
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sCommonRegs.EECR2 = hrtim_eecr2;
+ hhrtim->Instance->sCommonRegs.EECR3 = hrtim_eecr3;
+ break;
+ }
+
+ case HRTIM_EVENT_10:
+ {
+ hrtim_eecr2 &= ~(HRTIM_EECR2_EE10SRC | HRTIM_EECR2_EE10POL | HRTIM_EECR2_EE10SNS);
+ hrtim_eecr2 |= ((pEventCfg->Source << 24U) & HRTIM_EECR2_EE10SRC);
+ hrtim_eecr2 |= ((pEventCfg->Polarity << 24U) & HRTIM_EECR2_EE10POL);
+ hrtim_eecr2 |= ((pEventCfg->Sensitivity << 24U) & HRTIM_EECR2_EE10SNS);
+ hrtim_eecr3 &= ~(HRTIM_EECR3_EE10F);
+ hrtim_eecr3 |= ((pEventCfg->Filter << 24U) & HRTIM_EECR3_EE10F);
+ /* Update the HRTIM registers */
+ hhrtim->Instance->sCommonRegs.EECR2 = hrtim_eecr2;
+ hhrtim->Instance->sCommonRegs.EECR3 = hrtim_eecr3;
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief Configure the timer counter reset
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * @param Event Event channel identifier
+ * @retval None
+ */
+static void HRTIM_TIM_ResetConfig(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t Event)
+{
+ switch (Event)
+ {
+ case HRTIM_EVENT_1:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_1;
+ break;
+ }
+
+ case HRTIM_EVENT_2:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_2;
+ break;
+ }
+
+ case HRTIM_EVENT_3:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_3;
+ break;
+ }
+
+ case HRTIM_EVENT_4:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_4;
+ break;
+ }
+
+ case HRTIM_EVENT_5:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_5;
+ break;
+ }
+
+ case HRTIM_EVENT_6:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_6;
+ break;
+ }
+
+ case HRTIM_EVENT_7:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_7;
+ break;
+ }
+
+ case HRTIM_EVENT_8:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_8;
+ break;
+ }
+
+ case HRTIM_EVENT_9:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_9;
+ break;
+ }
+
+ case HRTIM_EVENT_10:
+ {
+ hhrtim->Instance->sTimerxRegs[TimerIdx].RSTxR = HRTIM_TIMRESETTRIGGER_EEV_10;
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief Return the interrupt to enable or disable according to the
+ * OC mode.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * @param OCChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval Interrupt to enable or disable
+ */
+static uint32_t HRTIM_GetITFromOCMode(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel)
+{
+ uint32_t hrtim_set;
+ uint32_t hrtim_reset;
+ uint32_t interrupt = 0U;
+
+ switch (OCChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ /* Retreives actual OC mode and set interrupt accordingly */
+ hrtim_set = hhrtim->Instance->sTimerxRegs[TimerIdx].SETx1R;
+ hrtim_reset = hhrtim->Instance->sTimerxRegs[TimerIdx].RSTx1R;
+
+ if (((hrtim_set & HRTIM_OUTPUTSET_TIMCMP1) == HRTIM_OUTPUTSET_TIMCMP1) &&
+ ((hrtim_reset & HRTIM_OUTPUTRESET_TIMCMP1) == HRTIM_OUTPUTRESET_TIMCMP1))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_TOGGLE */
+ interrupt = HRTIM_TIM_IT_CMP1;
+ }
+ else if (((hrtim_set & HRTIM_OUTPUTSET_TIMCMP1) == HRTIM_OUTPUTSET_TIMCMP1) &&
+ (hrtim_reset == 0U))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_ACTIVE */
+ interrupt = HRTIM_TIM_IT_SET1;
+ }
+ else if ((hrtim_set == 0U) &&
+ ((hrtim_reset & HRTIM_OUTPUTRESET_TIMCMP1) == HRTIM_OUTPUTRESET_TIMCMP1))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_INACTIVE */
+ interrupt = HRTIM_TIM_IT_RST1;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ /* Retreives actual OC mode and set interrupt accordingly */
+ hrtim_set = hhrtim->Instance->sTimerxRegs[TimerIdx].SETx2R;
+ hrtim_reset = hhrtim->Instance->sTimerxRegs[TimerIdx].RSTx2R;
+
+ if (((hrtim_set & HRTIM_OUTPUTSET_TIMCMP2) == HRTIM_OUTPUTSET_TIMCMP2) &&
+ ((hrtim_reset & HRTIM_OUTPUTRESET_TIMCMP2) == HRTIM_OUTPUTRESET_TIMCMP2))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_TOGGLE */
+ interrupt = HRTIM_TIM_IT_CMP2;
+ }
+ else if (((hrtim_set & HRTIM_OUTPUTSET_TIMCMP2) == HRTIM_OUTPUTSET_TIMCMP2) &&
+ (hrtim_reset == 0U))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_ACTIVE */
+ interrupt = HRTIM_TIM_IT_SET2;
+ }
+ else if ((hrtim_set == 0U) &&
+ ((hrtim_reset & HRTIM_OUTPUTRESET_TIMCMP2) == HRTIM_OUTPUTRESET_TIMCMP2))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_INACTIVE */
+ interrupt = HRTIM_TIM_IT_RST2;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return interrupt;
+}
+
+/**
+ * @brief Return the DMA request to enable or disable according to the
+ * OC mode.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * @param OCChannel Timer output
+ * This parameter can be one of the following values:
+ * @arg HRTIM_OUTPUT_TA1: Timer A - Output 1
+ * @arg HRTIM_OUTPUT_TA2: Timer A - Output 2
+ * @arg HRTIM_OUTPUT_TB1: Timer B - Output 1
+ * @arg HRTIM_OUTPUT_TB2: Timer B - Output 2
+ * @arg HRTIM_OUTPUT_TC1: Timer C - Output 1
+ * @arg HRTIM_OUTPUT_TC2: Timer C - Output 2
+ * @arg HRTIM_OUTPUT_TD1: Timer D - Output 1
+ * @arg HRTIM_OUTPUT_TD2: Timer D - Output 2
+ * @arg HRTIM_OUTPUT_TE1: Timer E - Output 1
+ * @arg HRTIM_OUTPUT_TE2: Timer E - Output 2
+ * @retval DMA request to enable or disable
+ */
+static uint32_t HRTIM_GetDMAFromOCMode(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx,
+ uint32_t OCChannel)
+{
+ uint32_t hrtim_set;
+ uint32_t hrtim_reset;
+ uint32_t dma_request = 0U;
+
+ switch (OCChannel)
+ {
+ case HRTIM_OUTPUT_TA1:
+ case HRTIM_OUTPUT_TB1:
+ case HRTIM_OUTPUT_TC1:
+ case HRTIM_OUTPUT_TD1:
+ case HRTIM_OUTPUT_TE1:
+ {
+ /* Retreives actual OC mode and set dma_request accordingly */
+ hrtim_set = hhrtim->Instance->sTimerxRegs[TimerIdx].SETx1R;
+ hrtim_reset = hhrtim->Instance->sTimerxRegs[TimerIdx].RSTx1R;
+
+ if (((hrtim_set & HRTIM_OUTPUTSET_TIMCMP1) == HRTIM_OUTPUTSET_TIMCMP1) &&
+ ((hrtim_reset & HRTIM_OUTPUTRESET_TIMCMP1) == HRTIM_OUTPUTRESET_TIMCMP1))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_TOGGLE */
+ dma_request = HRTIM_TIM_DMA_CMP1;
+ }
+ else if (((hrtim_set & HRTIM_OUTPUTSET_TIMCMP1) == HRTIM_OUTPUTSET_TIMCMP1) &&
+ (hrtim_reset == 0U))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_ACTIVE */
+ dma_request = HRTIM_TIM_DMA_SET1;
+ }
+ else if ((hrtim_set == 0U) &&
+ ((hrtim_reset & HRTIM_OUTPUTRESET_TIMCMP1) == HRTIM_OUTPUTRESET_TIMCMP1))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_INACTIVE */
+ dma_request = HRTIM_TIM_DMA_RST1;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ break;
+ }
+
+ case HRTIM_OUTPUT_TA2:
+ case HRTIM_OUTPUT_TB2:
+ case HRTIM_OUTPUT_TC2:
+ case HRTIM_OUTPUT_TD2:
+ case HRTIM_OUTPUT_TE2:
+ {
+ /* Retreives actual OC mode and set dma_request accordingly */
+ hrtim_set = hhrtim->Instance->sTimerxRegs[TimerIdx].SETx2R;
+ hrtim_reset = hhrtim->Instance->sTimerxRegs[TimerIdx].RSTx2R;
+
+ if (((hrtim_set & HRTIM_OUTPUTSET_TIMCMP2) == HRTIM_OUTPUTSET_TIMCMP2) &&
+ ((hrtim_reset & HRTIM_OUTPUTRESET_TIMCMP2) == HRTIM_OUTPUTRESET_TIMCMP2))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_TOGGLE */
+ dma_request = HRTIM_TIM_DMA_CMP2;
+ }
+ else if (((hrtim_set & HRTIM_OUTPUTSET_TIMCMP2) == HRTIM_OUTPUTSET_TIMCMP2) &&
+ (hrtim_reset == 0U))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_ACTIVE */
+ dma_request = HRTIM_TIM_DMA_SET2;
+ }
+ else if ((hrtim_set == 0U) &&
+ ((hrtim_reset & HRTIM_OUTPUTRESET_TIMCMP2) == HRTIM_OUTPUTRESET_TIMCMP2))
+ {
+ /* OC mode: HRTIM_BASICOCMODE_INACTIVE */
+ dma_request = HRTIM_TIM_DMA_RST2;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return dma_request;
+}
+
+static DMA_HandleTypeDef * HRTIM_GetDMAHandleFromTimerIdx(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ DMA_HandleTypeDef * hdma = (DMA_HandleTypeDef *)NULL;
+
+ switch (TimerIdx)
+ {
+ case HRTIM_TIMERINDEX_MASTER:
+ {
+ hdma = hhrtim->hdmaMaster;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_A:
+ {
+ hdma = hhrtim->hdmaTimerA;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_B:
+ {
+ hdma = hhrtim->hdmaTimerB;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_C:
+ {
+ hdma = hhrtim->hdmaTimerC;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_D:
+ {
+ hdma = hhrtim->hdmaTimerD;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_E:
+ {
+ hdma = hhrtim->hdmaTimerE;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return hdma;
+}
+
+static uint32_t GetTimerIdxFromDMAHandle(HRTIM_HandleTypeDef * hhrtim,
+ DMA_HandleTypeDef * hdma)
+{
+ uint32_t timed_idx = 0xFFFFFFFFU;
+
+ if (hdma == hhrtim->hdmaMaster)
+ {
+ timed_idx = HRTIM_TIMERINDEX_MASTER;
+ }
+ else if (hdma == hhrtim->hdmaTimerA)
+ {
+ timed_idx = HRTIM_TIMERINDEX_TIMER_A;
+ }
+ else if (hdma == hhrtim->hdmaTimerB)
+ {
+ timed_idx = HRTIM_TIMERINDEX_TIMER_B;
+ }
+ else if (hdma == hhrtim->hdmaTimerC)
+ {
+ timed_idx = HRTIM_TIMERINDEX_TIMER_C;
+ }
+ else if (hdma == hhrtim->hdmaTimerD)
+ {
+ timed_idx = HRTIM_TIMERINDEX_TIMER_D;
+ }
+ else if (hdma == hhrtim->hdmaTimerE)
+ {
+ timed_idx = HRTIM_TIMERINDEX_TIMER_E;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ return timed_idx;
+}
+
+/**
+ * @brief Force an immediate transfer from the preload to the active
+ * registers.
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * @retval None
+ */
+static void HRTIM_ForceRegistersUpdate(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ switch (TimerIdx)
+ {
+ case HRTIM_TIMERINDEX_MASTER:
+ {
+ hhrtim->Instance->sCommonRegs.CR2 |= HRTIM_CR2_MSWU;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_A:
+ {
+ hhrtim->Instance->sCommonRegs.CR2 |= HRTIM_CR2_TASWU;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_B:
+ {
+ hhrtim->Instance->sCommonRegs.CR2 |= HRTIM_CR2_TBSWU;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_C:
+ {
+ hhrtim->Instance->sCommonRegs.CR2 |= HRTIM_CR2_TCSWU;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_D:
+ {
+ hhrtim->Instance->sCommonRegs.CR2 |= HRTIM_CR2_TDSWU;
+ break;
+ }
+
+ case HRTIM_TIMERINDEX_TIMER_E:
+ {
+ hhrtim->Instance->sCommonRegs.CR2 |= HRTIM_CR2_TESWU;
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+
+/**
+ * @brief HRTIM interrupts service routine
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @retval None
+ */
+static void HRTIM_HRTIM_ISR(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Fault 1 event */
+ if(__HAL_HRTIM_GET_FLAG(hhrtim, HRTIM_FLAG_FLT1) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_GET_ITSTATUS(hhrtim, HRTIM_IT_FLT1) != RESET)
+ {
+ __HAL_HRTIM_CLEAR_IT(hhrtim, HRTIM_IT_FLT1);
+
+ /* Invoke Fault 1 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Fault1Callback(hhrtim);
+#else
+ HAL_HRTIM_Fault1Callback(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Fault 2 event */
+ if(__HAL_HRTIM_GET_FLAG(hhrtim, HRTIM_FLAG_FLT2) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_GET_ITSTATUS(hhrtim, HRTIM_IT_FLT2) != RESET)
+ {
+ __HAL_HRTIM_CLEAR_IT(hhrtim, HRTIM_IT_FLT2);
+
+ /* Invoke Fault 2 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Fault2Callback(hhrtim);
+#else
+ HAL_HRTIM_Fault2Callback(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Fault 3 event */
+ if(__HAL_HRTIM_GET_FLAG(hhrtim, HRTIM_FLAG_FLT3) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_GET_ITSTATUS(hhrtim, HRTIM_IT_FLT3) != RESET)
+ {
+ __HAL_HRTIM_CLEAR_IT(hhrtim, HRTIM_IT_FLT3);
+
+ /* Invoke Fault 3 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Fault3Callback(hhrtim);
+#else
+ HAL_HRTIM_Fault3Callback(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Fault 4 event */
+ if(__HAL_HRTIM_GET_FLAG(hhrtim, HRTIM_FLAG_FLT4) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_GET_ITSTATUS(hhrtim, HRTIM_IT_FLT4) != RESET)
+ {
+ __HAL_HRTIM_CLEAR_IT(hhrtim, HRTIM_IT_FLT4);
+
+ /* Invoke Fault 4 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Fault4Callback(hhrtim);
+#else
+ HAL_HRTIM_Fault4Callback(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Fault 5 event */
+ if(__HAL_HRTIM_GET_FLAG(hhrtim, HRTIM_FLAG_FLT5) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_GET_ITSTATUS(hhrtim, HRTIM_IT_FLT5) != RESET)
+ {
+ __HAL_HRTIM_CLEAR_IT(hhrtim, HRTIM_IT_FLT5);
+
+ /* Invoke Fault 5 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Fault5Callback(hhrtim);
+#else
+ HAL_HRTIM_Fault5Callback(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* System fault event */
+ if(__HAL_HRTIM_GET_FLAG(hhrtim, HRTIM_FLAG_SYSFLT) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_GET_ITSTATUS(hhrtim, HRTIM_IT_SYSFLT) != RESET)
+ {
+ __HAL_HRTIM_CLEAR_IT(hhrtim, HRTIM_IT_SYSFLT);
+
+ /* Invoke System fault event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->SystemFaultCallback(hhrtim);
+#else
+ HAL_HRTIM_SystemFaultCallback(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+* @brief Master timer interrupts service routine
+* @param hhrtim pointer to HAL HRTIM handle
+* @retval None
+*/
+static void HRTIM_Master_ISR(HRTIM_HandleTypeDef * hhrtim)
+{
+ /* Burst mode period event */
+ if(__HAL_HRTIM_GET_FLAG(hhrtim, HRTIM_FLAG_BMPER) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_GET_ITSTATUS(hhrtim, HRTIM_IT_BMPER) != RESET)
+ {
+ __HAL_HRTIM_CLEAR_IT(hhrtim, HRTIM_IT_BMPER);
+
+ /* Invoke Burst mode period event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->BurstModePeriodCallback(hhrtim);
+#else
+ HAL_HRTIM_BurstModePeriodCallback(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Master timer compare 1 event */
+ if(__HAL_HRTIM_MASTER_GET_FLAG(hhrtim, HRTIM_MASTER_FLAG_MCMP1) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_MASTER_GET_ITSTATUS(hhrtim, HRTIM_MASTER_IT_MCMP1) != RESET)
+ {
+ __HAL_HRTIM_MASTER_CLEAR_IT(hhrtim, HRTIM_MASTER_IT_MCMP1);
+
+ /* Invoke compare 1 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Compare1EventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_Compare1EventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Master timer compare 2 event */
+ if(__HAL_HRTIM_MASTER_GET_FLAG(hhrtim, HRTIM_MASTER_FLAG_MCMP2) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_MASTER_GET_ITSTATUS(hhrtim, HRTIM_MASTER_IT_MCMP2) != RESET)
+ {
+ __HAL_HRTIM_MASTER_CLEAR_IT(hhrtim, HRTIM_MASTER_IT_MCMP2);
+
+ /* Invoke compare 2 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Compare2EventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_Compare2EventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Master timer compare 3 event */
+ if(__HAL_HRTIM_MASTER_GET_FLAG(hhrtim, HRTIM_MASTER_FLAG_MCMP3) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_MASTER_GET_ITSTATUS(hhrtim, HRTIM_MASTER_IT_MCMP3) != RESET)
+ {
+ __HAL_HRTIM_MASTER_CLEAR_IT(hhrtim, HRTIM_MASTER_IT_MCMP3);
+
+ /* Invoke compare 3 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Compare3EventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_Compare3EventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Master timer compare 4 event */
+ if(__HAL_HRTIM_MASTER_GET_FLAG(hhrtim, HRTIM_MASTER_FLAG_MCMP4) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_MASTER_GET_ITSTATUS(hhrtim, HRTIM_MASTER_IT_MCMP4) != RESET)
+ {
+ __HAL_HRTIM_MASTER_CLEAR_IT(hhrtim, HRTIM_MASTER_IT_MCMP4);
+
+ /* Invoke compare 4 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Compare4EventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_Compare4EventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Master timer repetition event */
+ if(__HAL_HRTIM_MASTER_GET_FLAG(hhrtim, HRTIM_MASTER_FLAG_MREP) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_MASTER_GET_ITSTATUS(hhrtim, HRTIM_MASTER_IT_MREP) != RESET)
+ {
+ __HAL_HRTIM_MASTER_CLEAR_IT(hhrtim, HRTIM_MASTER_IT_MREP);
+
+ /* Invoke repetition event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->RepetitionEventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_RepetitionEventCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Synchronization input event */
+ if(__HAL_HRTIM_MASTER_GET_FLAG(hhrtim, HRTIM_MASTER_FLAG_SYNC) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_MASTER_GET_ITSTATUS(hhrtim, HRTIM_MASTER_IT_SYNC) != RESET)
+ {
+ __HAL_HRTIM_MASTER_CLEAR_IT(hhrtim, HRTIM_MASTER_IT_SYNC);
+
+ /* Invoke synchronization event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->SynchronizationEventCallback(hhrtim);
+#else
+ HAL_HRTIM_SynchronizationEventCallback(hhrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Master timer registers update event */
+ if(__HAL_HRTIM_MASTER_GET_FLAG(hhrtim, HRTIM_MASTER_FLAG_MUPD) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_MASTER_GET_ITSTATUS(hhrtim, HRTIM_MASTER_IT_MUPD) != RESET)
+ {
+ __HAL_HRTIM_MASTER_CLEAR_IT(hhrtim, HRTIM_MASTER_IT_MUPD);
+
+ /* Invoke registers update event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->RegistersUpdateCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_RegistersUpdateCallback(hhrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @brief Timer interrupts service routine
+ * @param hhrtim pointer to HAL HRTIM handle
+ * @param TimerIdx Timer index
+ * This parameter can be one of the following values:
+ * @arg HRTIM_TIMERINDEX_TIMER_A for timer A
+ * @arg HRTIM_TIMERINDEX_TIMER_B for timer B
+ * @arg HRTIM_TIMERINDEX_TIMER_C for timer C
+ * @arg HRTIM_TIMERINDEX_TIMER_D for timer D
+ * @arg HRTIM_TIMERINDEX_TIMER_E for timer E
+ * @retval None
+*/
+static void HRTIM_Timer_ISR(HRTIM_HandleTypeDef * hhrtim,
+ uint32_t TimerIdx)
+{
+ /* Timer compare 1 event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_CMP1) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP1) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP1);
+
+ /* Invoke compare 1 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Compare1EventCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Compare1EventCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer compare 2 event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_CMP2) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP2) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP2);
+
+ /* Invoke compare 2 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Compare2EventCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Compare2EventCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer compare 3 event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_CMP3) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP3) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP3);
+
+ /* Invoke compare 3 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Compare3EventCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Compare3EventCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer compare 4 event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_CMP4) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP4) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CMP4);
+
+ /* Invoke compare 4 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Compare4EventCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Compare4EventCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer repetition event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_REP) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_REP) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_REP);
+
+ /* Invoke repetition event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->RepetitionEventCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_RepetitionEventCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer registers update event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_UPD) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_UPD) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_UPD);
+
+ /* Invoke registers update event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->RegistersUpdateCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_RegistersUpdateCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer capture 1 event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_CPT1) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_CPT1) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CPT1);
+
+ /* Invoke capture 1 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Capture1EventCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Capture1EventCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer capture 2 event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_CPT2) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_CPT2) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_CPT2);
+
+ /* Invoke capture 2 event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Capture2EventCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Capture2EventCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer output 1 set event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_SET1) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_SET1) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_SET1);
+
+ /* Invoke output 1 set event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Output1SetCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Output1SetCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer output 1 reset event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_RST1) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_RST1) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_RST1);
+
+ /* Invoke output 1 reset event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Output1ResetCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Output1ResetCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer output 2 set event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_SET2) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_SET2) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_SET2);
+
+ /* Invoke output 2 set event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Output2SetCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Output2SetCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer output 2 reset event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_RST2) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_RST2) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_RST2);
+
+ /* Invoke output 2 reset event callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->Output2ResetCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_Output2ResetCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Timer reset event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_RST) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_RST) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_RST);
+
+ /* Invoke timer reset callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->CounterResetCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_CounterResetCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Delayed protection event */
+ if(__HAL_HRTIM_TIMER_GET_FLAG(hhrtim, TimerIdx, HRTIM_TIM_FLAG_DLYPRT) != (uint32_t)RESET)
+ {
+ if(__HAL_HRTIM_TIMER_GET_ITSTATUS(hhrtim, TimerIdx, HRTIM_TIM_IT_DLYPRT) != RESET)
+ {
+ __HAL_HRTIM_TIMER_CLEAR_IT(hhrtim, TimerIdx, HRTIM_TIM_IT_DLYPRT);
+
+ /* Invoke delayed protection callback */
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hhrtim->DelayedProtectionCallback(hhrtim, TimerIdx);
+#else
+ HAL_HRTIM_DelayedProtectionCallback(hhrtim, TimerIdx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @brief DMA callback invoked upon master timer related DMA request completion
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void HRTIM_DMAMasterCplt(DMA_HandleTypeDef *hdma)
+{
+ HRTIM_HandleTypeDef * hrtim = (HRTIM_HandleTypeDef *)((DMA_HandleTypeDef* )hdma)->Parent;
+
+ if ((hrtim->Instance->sMasterRegs.MDIER & HRTIM_MASTER_DMA_MCMP1) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Compare1EventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_Compare1EventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sMasterRegs.MDIER & HRTIM_MASTER_DMA_MCMP2) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Compare2EventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_Compare2EventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sMasterRegs.MDIER & HRTIM_MASTER_DMA_MCMP3) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Compare3EventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_Compare3EventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sMasterRegs.MDIER & HRTIM_MASTER_DMA_MCMP4) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Compare4EventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_Compare4EventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sMasterRegs.MDIER & HRTIM_MASTER_DMA_SYNC) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->SynchronizationEventCallback(hrtim);
+#else
+ HAL_HRTIM_SynchronizationEventCallback(hrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sMasterRegs.MDIER & HRTIM_MASTER_DMA_MUPD) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->RegistersUpdateCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_RegistersUpdateCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sMasterRegs.MDIER & HRTIM_MASTER_DMA_MREP) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->RepetitionEventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#else
+ HAL_HRTIM_RepetitionEventCallback(hrtim, HRTIM_TIMERINDEX_MASTER);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* nothing to do */
+ }
+}
+
+/**
+ * @brief DMA callback invoked upon timer A..E related DMA request completion
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void HRTIM_DMATimerxCplt(DMA_HandleTypeDef *hdma)
+{
+ uint8_t timer_idx;
+
+ HRTIM_HandleTypeDef * hrtim = (HRTIM_HandleTypeDef *)((DMA_HandleTypeDef* )hdma)->Parent;
+
+ timer_idx = (uint8_t)GetTimerIdxFromDMAHandle(hrtim, hdma);
+
+ if ( !IS_HRTIM_TIMING_UNIT(timer_idx) ) {return;}
+
+ if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_CMP1) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Compare1EventCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Compare1EventCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_CMP2) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Compare2EventCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Compare2EventCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_CMP3) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Compare3EventCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Compare3EventCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_CMP4) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Compare4EventCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Compare4EventCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_UPD) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->RegistersUpdateCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_RegistersUpdateCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_CPT1) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Capture1EventCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Capture1EventCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_CPT2) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Capture2EventCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Capture2EventCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_SET1) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Output1SetCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Output1SetCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_RST1) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Output1ResetCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Output1ResetCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_SET2) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Output2SetCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Output2SetCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_RST2) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->Output2ResetCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_Output2ResetCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_RST) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->CounterResetCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_CounterResetCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_DLYPRT) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->DelayedProtectionCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_DelayedProtectionCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else if ((hrtim->Instance->sTimerxRegs[timer_idx].TIMxDIER & HRTIM_TIM_DMA_REP) != (uint32_t)RESET)
+ {
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->RepetitionEventCallback(hrtim, timer_idx);
+#else
+ HAL_HRTIM_RepetitionEventCallback(hrtim, timer_idx);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* nothing to do */
+ }
+}
+
+/**
+* @brief DMA error callback
+* @param hdma pointer to DMA handle.
+* @retval None
+*/
+static void HRTIM_DMAError(DMA_HandleTypeDef *hdma)
+{
+ HRTIM_HandleTypeDef * hrtim = (HRTIM_HandleTypeDef *)((DMA_HandleTypeDef* )hdma)->Parent;
+
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->ErrorCallback(hrtim);
+#else
+ HAL_HRTIM_ErrorCallback(hrtim);
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA callback invoked upon burst DMA transfer completion
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void HRTIM_BurstDMACplt(DMA_HandleTypeDef *hdma)
+{
+ HRTIM_HandleTypeDef * hrtim = (HRTIM_HandleTypeDef *)((DMA_HandleTypeDef* )hdma)->Parent;
+
+#if (USE_HAL_HRTIM_REGISTER_CALLBACKS == 1)
+ hrtim->BurstDMATransferCallback(hrtim, GetTimerIdxFromDMAHandle(hrtim, hdma));
+#else
+ HAL_HRTIM_BurstDMATransferCallback(hrtim, GetTimerIdxFromDMAHandle(hrtim, hdma));
+#endif /* USE_HAL_HRTIM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HRTIM1 */
+
+#endif /* HAL_HRTIM_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_hsem.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hsem.c
new file mode 100644
index 0000000000..1fab0cefa5
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_hsem.c
@@ -0,0 +1,441 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ *
+ @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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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)
+#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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2c.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2c.c
new file mode 100644
index 0000000000..7c05d16f6f
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2c.c
@@ -0,0 +1,6635 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ @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 @ref 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 @ref HAL_I2C_Init(), configures also the low level Hardware
+ (GPIO, CLOCK, NVIC...etc) by calling the customized @ref HAL_I2C_MspInit(&hi2c) API.
+
+ (#) To check if target device is ready for communication, use the function @ref 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 @ref HAL_I2C_Master_Transmit()
+ (+) Receive in master mode an amount of data in blocking mode using @ref HAL_I2C_Master_Receive()
+ (+) Transmit in slave mode an amount of data in blocking mode using @ref HAL_I2C_Slave_Transmit()
+ (+) Receive in slave mode an amount of data in blocking mode using @ref HAL_I2C_Slave_Receive()
+
+ *** Polling mode IO MEM operation ***
+ =====================================
+ [..]
+ (+) Write an amount of data in blocking mode to a specific memory address using @ref HAL_I2C_Mem_Write()
+ (+) Read an amount of data in blocking mode from a specific memory address using @ref HAL_I2C_Mem_Read()
+
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Transmit in master mode an amount of data in non-blocking mode using @ref HAL_I2C_Master_Transmit_IT()
+ (+) At transmission end of transfer, @ref HAL_I2C_MasterTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MasterTxCpltCallback()
+ (+) Receive in master mode an amount of data in non-blocking mode using @ref HAL_I2C_Master_Receive_IT()
+ (+) At reception end of transfer, @ref HAL_I2C_MasterRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MasterRxCpltCallback()
+ (+) Transmit in slave mode an amount of data in non-blocking mode using @ref HAL_I2C_Slave_Transmit_IT()
+ (+) At transmission end of transfer, @ref HAL_I2C_SlaveTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_SlaveTxCpltCallback()
+ (+) Receive in slave mode an amount of data in non-blocking mode using @ref HAL_I2C_Slave_Receive_IT()
+ (+) At reception end of transfer, @ref HAL_I2C_SlaveRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_SlaveRxCpltCallback()
+ (+) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
+ (+) Abort a master I2C process communication with Interrupt using @ref HAL_I2C_Master_Abort_IT()
+ (+) End of abort process, @ref HAL_I2C_AbortCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_AbortCpltCallback()
+ (+) Discard a slave I2C process communication using @ref __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 @ref I2C_XFEROPTIONS and are listed below:
+ (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functionnal is same as associated interfaces in no sequential mode
+ (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address
+ and data to transfer without a final stop condition
+ (++) I2C_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 @ref HAL_I2C_Master_Seq_Transmit_IT() then @ref HAL_I2C_Master_Seq_Transmit_IT()
+ or @ref HAL_I2C_Master_Seq_Transmit_DMA() then @ref 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(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME)
+ or HAL_I2C_Master_Seq_Receive_IT(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME)
+ or HAL_I2C_Master_Seq_Transmit_DMA(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME)
+ or HAL_I2C_Master_Seq_Receive_DMA(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 oposite 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(option I2C_FIRST_FRAME then I2C_OTHER_FRAME)
+ or HAL_I2C_Master_Seq_Receive_IT(option I2C_FIRST_FRAME then I2C_OTHER_FRAME)
+ or HAL_I2C_Master_Seq_Transmit_DMA(option I2C_FIRST_FRAME then I2C_OTHER_FRAME)
+ or HAL_I2C_Master_Seq_Receive_DMA(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.
+
+ (+) Differents sequential I2C interfaces are listed below:
+ (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using @ref HAL_I2C_Master_Seq_Transmit_IT()
+ or using @ref HAL_I2C_Master_Seq_Transmit_DMA()
+ (+++) At transmission end of current frame transfer, @ref HAL_I2C_MasterTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MasterTxCpltCallback()
+ (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using @ref HAL_I2C_Master_Seq_Receive_IT()
+ or using @ref HAL_I2C_Master_Seq_Receive_DMA()
+ (+++) At reception end of current frame transfer, @ref HAL_I2C_MasterRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MasterRxCpltCallback()
+ (++) Abort a master IT or DMA I2C process communication with Interrupt using @ref HAL_I2C_Master_Abort_IT()
+ (+++) End of abort process, @ref HAL_I2C_AbortCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_AbortCpltCallback()
+ (++) Enable/disable the Address listen mode in slave I2C mode using @ref HAL_I2C_EnableListen_IT() @ref HAL_I2C_DisableListen_IT()
+ (+++) When address slave I2C match, @ref HAL_I2C_AddrCallback() is executed and user can
+ add his own code to check the Address Match Code and the transmission direction request by master (Write/Read).
+ (+++) At Listen mode end @ref HAL_I2C_ListenCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_ListenCpltCallback()
+ (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using @ref HAL_I2C_Slave_Seq_Transmit_IT()
+ or using @ref HAL_I2C_Slave_Seq_Transmit_DMA()
+ (+++) At transmission end of current frame transfer, @ref HAL_I2C_SlaveTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_SlaveTxCpltCallback()
+ (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using @ref HAL_I2C_Slave_Seq_Receive_IT()
+ or using @ref HAL_I2C_Slave_Seq_Receive_DMA()
+ (+++) At reception end of current frame transfer, @ref HAL_I2C_SlaveRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_SlaveRxCpltCallback()
+ (++) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
+ (++) Discard a slave I2C process communication using @ref __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
+ @ref HAL_I2C_Mem_Write_IT()
+ (+) At Memory end of write transfer, @ref HAL_I2C_MemTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MemTxCpltCallback()
+ (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using
+ @ref HAL_I2C_Mem_Read_IT()
+ (+) At Memory end of read transfer, @ref HAL_I2C_MemRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MemRxCpltCallback()
+ (+) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using
+ @ref HAL_I2C_Master_Transmit_DMA()
+ (+) At transmission end of transfer, @ref HAL_I2C_MasterTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MasterTxCpltCallback()
+ (+) Receive in master mode an amount of data in non-blocking mode (DMA) using
+ @ref HAL_I2C_Master_Receive_DMA()
+ (+) At reception end of transfer, @ref HAL_I2C_MasterRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MasterRxCpltCallback()
+ (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using
+ @ref HAL_I2C_Slave_Transmit_DMA()
+ (+) At transmission end of transfer, @ref HAL_I2C_SlaveTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_SlaveTxCpltCallback()
+ (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using
+ @ref HAL_I2C_Slave_Receive_DMA()
+ (+) At reception end of transfer, @ref HAL_I2C_SlaveRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_SlaveRxCpltCallback()
+ (+) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
+ (+) Abort a master I2C process communication with Interrupt using @ref HAL_I2C_Master_Abort_IT()
+ (+) End of abort process, @ref HAL_I2C_AbortCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_AbortCpltCallback()
+ (+) Discard a slave I2C process communication using @ref __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
+ @ref HAL_I2C_Mem_Write_DMA()
+ (+) At Memory end of write transfer, @ref HAL_I2C_MemTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MemTxCpltCallback()
+ (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using
+ @ref HAL_I2C_Mem_Read_DMA()
+ (+) At Memory end of read transfer, @ref HAL_I2C_MemRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_MemRxCpltCallback()
+ (+) In case of transfer Error, @ref HAL_I2C_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer @ref HAL_I2C_ErrorCallback()
+
+
+ *** I2C HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in I2C HAL driver.
+
+ (+) @ref __HAL_I2C_ENABLE: Enable the I2C peripheral
+ (+) @ref __HAL_I2C_DISABLE: Disable the I2C peripheral
+ (+) @ref __HAL_I2C_GENERATE_NACK: Generate a Non-Acknowledge I2C peripheral in Slave mode
+ (+) @ref __HAL_I2C_GET_FLAG: Check whether the specified I2C flag is set or not
+ (+) @ref __HAL_I2C_CLEAR_FLAG: Clear the specified I2C pending flag
+ (+) @ref __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt
+ (+) @ref __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 @ref HAL_I2C_RegisterCallback() or @ref HAL_I2C_RegisterAddrCallback()
+ to register an interrupt callback.
+ [..]
+ Function @ref 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 : @ref HAL_I2C_RegisterAddrCallback().
+ [..]
+ Use function @ref HAL_I2C_UnRegisterCallback to reset a callback to the default
+ weak function.
+ @ref 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 : @ref HAL_I2C_UnRegisterAddrCallback().
+ [..]
+ By default, after the @ref HAL_I2C_Init() and when the state is @ref HAL_I2C_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples @ref HAL_I2C_MasterTxCpltCallback(), @ref HAL_I2C_MasterRxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the @ref HAL_I2C_Init()/ @ref HAL_I2C_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ If MspInit or MspDeInit are not null, the @ref HAL_I2C_Init()/ @ref HAL_I2C_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+ [..]
+ Callbacks can be registered/unregistered in @ref HAL_I2C_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in @ref HAL_I2C_STATE_READY or @ref 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 @ref HAL_I2C_RegisterCallback() before calling @ref HAL_I2C_DeInit()
+ or @ref 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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 SlaveAddr_SHIFT 7U
+#define SlaveAddr_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 macro -------------------------------------------------------------*/
+/* 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_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_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_IsAcknowledgeFailed(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)
+ {
+ 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
+ * @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;
+ }
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2c);
+ return status;
+}
+
+/**
+ * @brief Unregister an I2C Callback
+ * I2C callback is redirected to the weak predefined callback
+ * @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;
+
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2c);
+ 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;
+ }
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2c);
+ 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;
+
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2c);
+ 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;
+
+ 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;
+
+ /* 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_WRITE);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, 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;
+
+ 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;
+
+ /* 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);
+
+ /* If 10bit addressing mode is selected */
+ if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ /* Wait until ADDR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_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;
+ 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 STOP flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Normal use case for Transmitter mode */
+ /* A NACK is generated to confirm the end of transfer */
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ }
+ else
+ {
+ return HAL_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->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--;
+ }
+
+ return HAL_ERROR;
+ }
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ }
+
+ /* 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 */
+ 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;
+
+ /* 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;
+
+ 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)
+ {
+ 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 */
+ /* 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);
+
+ /* 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)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in master mode an amount of data in non-blocking mode with 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, 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 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;
+
+ 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)
+ {
+ /* 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;
+ }
+
+ 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)
+{
+ uint32_t tickstart;
+ uint32_t xfermode;
+
+ /* 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);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* 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 and Memory Address */
+ if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+
+ /* 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_NO_STARTSTOP);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: 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)
+{
+ uint32_t tickstart;
+ uint32_t xfermode;
+
+ /* 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);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* 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 and Memory Address */
+ if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+
+ /* 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_READ);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: 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)
+{
+ uint32_t tickstart;
+ uint32_t xfermode;
+ 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);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* 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;
+ }
+
+ /* Send Slave Address and Memory Address */
+ if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+
+
+ 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 */
+ /* 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_NO_STARTSTOP);
+
+ /* 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;
+ }
+
+ 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)
+{
+ uint32_t tickstart;
+ uint32_t xfermode;
+ 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);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* 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;
+ }
+
+ /* Send Slave Address and Memory Address */
+ if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+
+ 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)
+ {
+ /* 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_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;
+ }
+
+ 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)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Device is ready */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Clear STOP Flag, auto generated with autoend*/
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+
+ /* Check if the maximum allowed number of trials has been reached */
+ if (I2C_Trials == Trials)
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __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;
+
+ /* 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 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 */
+ 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_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;
+
+ /* 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 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)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 set NBYTES to write */
+ 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 */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief 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, 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 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)
+{
+ /* 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;
+
+ if (I2C_GET_DIR(hi2c) == I2C_DIRECTION_RECEIVE)
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Sequential 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)
+{
+ 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;
+ }
+
+ if (I2C_GET_DIR(hi2c) == I2C_DIRECTION_RECEIVE)
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, STOP, NACK, ADDR interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+
+ 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)
+{
+ /* 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;
+
+ if (I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT)
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief 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)
+{
+ 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;
+ }
+
+ if (I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT)
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+
+ 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 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)
+{
+ if (hi2c->Mode == HAL_I2C_MODE_MASTER)
+ {
+ /* 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)
+{
+ /* 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(I2C_HandleTypeDef *hi2c)
+{
+ /* Return I2C handle state */
+ return hi2c->State;
+}
+
+/**
+ * @brief Returns the I2C Master, Slave, Memory or no mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for I2C module
+ * @retval HAL mode
+ */
+HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c)
+{
+ return hi2c->Mode;
+}
+
+/**
+* @brief Return the I2C error code.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+* @retval I2C Error Code
+*/
+uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c)
+{
+ return hi2c->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup I2C_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode 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_TXIS) != RESET) && (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TXI) != RESET))
+ {
+ /* 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 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);
+ }
+
+ 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 Datas have already been sent */
+ /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */
+ if (hi2c->XferCount > 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 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);
+ }
+
+ 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 (__HAL_DMA_GET_COUNTER(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 (__HAL_DMA_GET_COUNTER(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 & SlaveAddr_MSK) == ((ownadd1code >> SlaveAddr_SHIFT) & SlaveAddr_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;
+ uint32_t tmp;
+
+ /* 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 */
+ tmp = (uint8_t)hi2c->Instance->RXDR;
+
+ UNUSED(tmp);
+ }
+
+ /* 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;
+ 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
+ {
+ /* 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)__HAL_DMA_GET_COUNTER(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)__HAL_DMA_GET_COUNTER(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;
+ }
+
+ 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 Tranfer */
+ 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);
+
+ /* If state is an abort treatment on goind, 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;
+ }
+ 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)
+{
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+
+ /* 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)
+{
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+ 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)
+{
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+
+ /* 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)
+{
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+ uint32_t tmpoptions = hi2c->XferOptions;
+
+ if ((__HAL_DMA_GET_COUNTER(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;
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+
+ if (hi2c->hdmatx != NULL)
+ {
+ if (__HAL_DMA_GET_COUNTER(hi2c->hdmatx) == 0U)
+ {
+ treatdmaerror = 1U;
+ }
+ }
+
+ if (hi2c->hdmarx != NULL)
+ {
+ if (__HAL_DMA_GET_COUNTER(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)
+{
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+
+ /* 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.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Flag Specifies the I2C flag to check.
+ * @param Status The new Flag status (SET or RESET).
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ 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 a NACK is detected */
+ if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ 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 a NACK is detected */
+ if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ 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)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)
+ {
+ /* Check if a NACK is detected */
+ if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check if a STOPF is detected */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)
+ {
+ /* 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 */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Check for the Timeout */
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles Acknowledge failed detection during an I2C Communication.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ /* Wait until STOP Flag is reset */
+ /* AutoEnd should be initiate after AF */
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ 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;
+ }
+ }
+ }
+
+ /* Clear NACKF Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set).
+ * @param hi2c I2C handle.
+ * @param DevAddress Specifies the slave address to be programmed.
+ * @param Size Specifies the number of bytes to be programmed.
+ * This parameter must be a value between 0 and 255.
+ * @param Mode New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_RELOAD_MODE Enable Reload mode .
+ * @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode.
+ * @arg @ref I2C_SOFTEND_MODE Enable Software end mode.
+ * @param Request New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition.
+ * @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0).
+ * @arg @ref I2C_GENERATE_START_READ Generate Restart for read request.
+ * @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request.
+ * @retval None
+ */
+static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_TRANSFER_MODE(Mode));
+ assert_param(IS_TRANSFER_REQUEST(Request));
+
+ /* 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)), \
+ (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | (uint32_t)Mode | (uint32_t)Request));
+}
+
+/**
+ * @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))
+ {
+ 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_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;
+ }
+ }
+ 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 RXI 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 TXI interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_RXI;
+ }
+
+ if (InterruptRequest == I2C_XFER_CPLT_IT)
+ {
+ /* Enable STOP interrupts */
+ tmpisr |= I2C_IT_STOPI;
+ }
+ }
+
+ /* 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 functionnal 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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2c_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2c_ex.c
new file mode 100644
index 0000000000..ea50ce31c5
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2c_ex.c
@@ -0,0 +1,339 @@
+/**
+ ******************************************************************************
+ * @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:
+ * + Extended features functions
+ *
+ @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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 Extended features functions
+ * @brief Extended features functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure Noise Filters
+ (+) Configure Wake Up Feature
+ (+) Configure Fast Mode Plus
+
+@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;
+ }
+}
+
+/**
+ * @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;
+ }
+}
+
+/**
+ * @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.
+ * @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.
+ * @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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2s.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2s.c
new file mode 100644
index 0000000000..1a6bec0451
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2s.c
@@ -0,0 +1,1946 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_i2s.c
+ * @author MCD Application Team
+ * @brief I2S HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Integrated Interchip Sound (I2S) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and Errors functions
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The I2S HAL driver can be used as follow:
+
+ (#) Declare a I2S_HandleTypeDef handle structure.
+ (#) Initialize the I2S low level resources by implement the HAL_I2S_MspInit() API:
+ (##) Enable the SPIx interface clock.
+ (##) I2S pins configuration:
+ (+++) Enable the clock for the I2S GPIOs.
+ (+++) Configure these I2S pins as alternate function pull-up.
+ (##) NVIC configuration if you need to use interrupt process (HAL_I2S_Transmit_IT()
+ and HAL_I2S_Receive_IT() APIs).
+ (+++) Configure the I2Sx interrupt priority.
+ (+++) Enable the NVIC I2S IRQ handle.
+ (##) DMA Configuration if you need to use DMA process (HAL_I2S_Transmit_DMA()
+ and HAL_I2S_Receive_DMA() APIs:
+ (+++) Declare a DMA handle structure for the Tx/Rx Stream/Channel.
+ (+++) Enable the DMAx interface clock.
+ (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
+ (+++) Configure the DMA Tx/Rx Stream/Channel.
+ (+++) Associate the initialized DMA handle to the I2S DMA Tx/Rx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
+ DMA Tx/Rx Stream/Channel.
+
+ (#) Program the Mode, Standard, Data Format, MCLK Output, Audio frequency and Polarity
+ using HAL_I2S_Init() function.
+
+ -@- The specific I2S interrupts (Transmission complete interrupt,
+ RXNE interrupt and Error Interrupts) will be managed using the macros
+ __HAL_I2S_ENABLE_IT() and __HAL_I2S_DISABLE_IT() inside the transmit and receive process.
+
+ (+@) External clock source is configured after setting correctly
+ the define constant EXTERNAL_CLOCK_VALUE in the stm32h7xx_hal_conf.h file.
+
+ (#) Three mode of operations are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Send an amount of data in blocking mode using HAL_I2S_Transmit()
+ (+) Receive an amount of data in blocking mode using HAL_I2S_Receive()
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Send an amount of data in non blocking mode using HAL_I2S_Transmit_IT()
+ (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback
+ (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_TxCpltCallback
+ (+) Receive an amount of data in non blocking mode using HAL_I2S_Receive_IT()
+ (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback
+ (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_RxCpltCallback
+ (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_I2S_ErrorCallback
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Send an amount of data in non blocking mode (DMA) using HAL_I2S_Transmit_DMA()
+ (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback
+ (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_TxCpltCallback
+ (+) Receive an amount of data in non blocking mode (DMA) using HAL_I2S_Receive_DMA()
+ (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback
+ (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_RxCpltCallback
+ (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_I2S_ErrorCallback
+ (+) Pause the DMA Transfer using HAL_I2S_DMAPause()
+ (+) Resume the DMA Transfer using HAL_I2S_DMAResume()
+ (+) Stop the DMA Transfer using HAL_I2S_DMAStop()
+
+ *** I2S HAL driver macros list ***
+ ===================================
+ [..]
+ Below the list of most used macros in I2S HAL driver.
+
+ (+) __HAL_I2S_ENABLE: Enable the specified SPI peripheral (in I2S mode)
+ (+) __HAL_I2S_DISABLE: Disable the specified SPI peripheral (in I2S mode)
+ (+) __HAL_I2S_ENABLE_IT : Enable the specified I2S interrupts
+ (+) __HAL_I2S_DISABLE_IT : Disable the specified I2S interrupts
+ (+) __HAL_I2S_GET_FLAG: Check whether the specified I2S flag is set or not
+
+ [..]
+ (@) You can refer to the I2S HAL driver header file for more useful macros
+
+ *** I2S HAL driver macros list ***
+ ===================================
+ [..]
+ Callback registration:
+
+ (#) The compilation flag USE_HAL_I2S_REGISTER_CALLBACKS when set to 1UL
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions HAL_I2S_RegisterCallback() to register an interrupt callback.
+
+ Function HAL_I2S_RegisterCallback() allows to register following callbacks:
+ (+) TxCpltCallback : I2S Tx Completed callback
+ (+) RxCpltCallback : I2S Rx Completed callback
+ (+) TxHalfCpltCallback : I2S Tx Half Completed callback
+ (+) RxHalfCpltCallback : I2S Rx Half Completed callback
+ (+) ErrorCallback : I2S Error callback
+ (+) MspInitCallback : I2S Msp Init callback
+ (+) MspDeInitCallback : I2S Msp DeInit callback
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+
+ (#) Use function HAL_I2S_UnRegisterCallback to reset a callback to the default
+ weak function.
+ HAL_I2S_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxCpltCallback : I2S Tx Completed callback
+ (+) RxCpltCallback : I2S Rx Completed callback
+ (+) TxHalfCpltCallback : I2S Tx Half Completed callback
+ (+) RxHalfCpltCallback : I2S Rx Half Completed callback
+ (+) ErrorCallback : I2S Error callback
+ (+) MspInitCallback : I2S Msp Init callback
+ (+) MspDeInitCallback : I2S Msp DeInit callback
+
+ By default, after the HAL_I2S_Init() and when the state is HAL_I2S_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples HAL_I2S_MasterTxCpltCallback(), HAL_I2S_MasterRxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the HAL_I2S_Init()/ HAL_I2S_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ If MspInit or MspDeInit are not null, the HAL_I2S_Init()/ HAL_I2S_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+
+ Callbacks can be registered/unregistered in HAL_I2S_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in HAL_I2S_STATE_READY or HAL_I2S_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_I2S_RegisterCallback() before calling HAL_I2S_DeInit()
+ or HAL_I2S_Init() function.
+
+ When The compilation define USE_HAL_I2S_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+#ifdef HAL_I2S_MODULE_ENABLED
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup I2S I2S
+ * @brief I2S HAL module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define I2S_TIMEOUT 0xFFFFUL
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup I2S_Private_Functions I2S Private Functions
+ * @{
+ */
+static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma);
+static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
+static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma);
+static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
+static void I2S_DMAError(DMA_HandleTypeDef *hdma);
+static void I2S_Transmit_16Bit_IT(I2S_HandleTypeDef *hi2s);
+static void I2S_Transmit_32Bit_IT(I2S_HandleTypeDef *hi2s);
+static void I2S_Receive_16Bit_IT(I2S_HandleTypeDef *hi2s);
+static void I2S_Receive_32Bit_IT(I2S_HandleTypeDef *hi2s);
+static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State,
+ uint32_t Timeout);
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+
+/** @defgroup I2S_Exported_Functions I2S Exported Functions
+ * @{
+ */
+
+/** @defgroup I2S_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to initialize and
+ de-initialize the I2Sx peripheral in simplex mode:
+
+ (+) User must Implement HAL_I2S_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_I2S_Init() to configure the selected device with
+ the selected configuration:
+ (++) Mode
+ (++) Standard
+ (++) Data Format
+ (++) MCLK Output
+ (++) Audio frequency
+ (++) Polarity
+
+ (+) Call the function HAL_I2S_DeInit() to restore the default configuration
+ of the selected I2Sx peripheral.
+ @endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the I2S according to the specified parameters
+ * in the I2S_InitTypeDef and create the associated handle.
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Init(I2S_HandleTypeDef *hi2s)
+{
+ uint32_t i2sdiv;
+ uint32_t i2sodd;
+ uint32_t packetlength;
+ uint32_t tmp;
+ uint32_t i2sclk;
+ uint32_t ispcm;
+
+ /* Check the I2S handle allocation */
+ if (hi2s == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the I2S parameters */
+ assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
+ assert_param(IS_I2S_MODE(hi2s->Init.Mode));
+ assert_param(IS_I2S_STANDARD(hi2s->Init.Standard));
+ assert_param(IS_I2S_DATA_FORMAT(hi2s->Init.DataFormat));
+ assert_param(IS_I2S_MCLK_OUTPUT(hi2s->Init.MCLKOutput));
+ assert_param(IS_I2S_AUDIO_FREQ(hi2s->Init.AudioFreq));
+ assert_param(IS_I2S_CPOL(hi2s->Init.CPOL));
+ assert_param(IS_I2S_FIRST_BIT(hi2s->Init.FirstBit));
+ assert_param(IS_I2S_WS_INVERSION(hi2s->Init.WSInversion));
+ assert_param(IS_I2S_DATA_24BIT_ALIGNMENT(hi2s->Init.Data24BitAlignment));
+ assert_param(IS_I2S_MASTER_KEEP_IO_STATE(hi2s->Init.MasterKeepIOState));
+
+ if (hi2s->State == HAL_I2S_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hi2s->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ /* Init the I2S Callback settings */
+ hi2s->TxCpltCallback = HAL_I2S_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ hi2s->RxCpltCallback = HAL_I2S_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ hi2s->TxHalfCpltCallback = HAL_I2S_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ hi2s->RxHalfCpltCallback = HAL_I2S_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ hi2s->ErrorCallback = HAL_I2S_ErrorCallback; /* Legacy weak ErrorCallback */
+
+ if (hi2s->MspInitCallback == NULL)
+ {
+ hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ hi2s->MspInitCallback(hi2s);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ HAL_I2S_MspInit(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+ }
+
+ hi2s->State = HAL_I2S_STATE_BUSY;
+
+ /* Disable the selected I2S peripheral */
+ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) == SPI_CR1_SPE)
+ {
+ /* Disable I2S peripheral */
+ __HAL_I2S_DISABLE(hi2s);
+ }
+
+ /* Clear I2S configuration register */
+ CLEAR_REG(hi2s->Instance->I2SCFGR);
+
+ if (IS_I2S_MASTER(hi2s->Init.Mode))
+ {
+ /*------------------------- I2SDIV and ODD Calculation ---------------------*/
+ /* If the requested audio frequency is not the default, compute the prescaler */
+ if (hi2s->Init.AudioFreq != I2S_AUDIOFREQ_DEFAULT)
+ {
+ /* Check the frame length (For the Prescaler computing) ********************/
+ if (hi2s->Init.DataFormat != I2S_DATAFORMAT_16B)
+ {
+ /* Channel length is 32 bits */
+ packetlength = 2UL;
+ }
+ else
+ {
+ /* Channel length is 16 bits */
+ packetlength = 1UL;
+ }
+
+ /* Check if PCM standard is used */
+ if ((hi2s->Init.Standard == I2S_STANDARD_PCM_SHORT) ||
+ (hi2s->Init.Standard == I2S_STANDARD_PCM_LONG))
+ {
+ ispcm = 1UL;
+ }
+ else
+ {
+ ispcm = 0UL;
+ }
+
+ /* Get the source clock value: based on System Clock value */
+#if defined (SPI_SPI6I2S_SUPPORT)
+ if (hi2s->Instance == SPI6)
+ {
+ /* SPI6 source clock */
+ i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
+ }
+ else
+ {
+ /* SPI1,SPI2 and SPI3 share the same source clock */
+ i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
+ }
+#else
+ /* SPI1,SPI2 and SPI3 share the same source clock */
+ i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
+#endif
+
+ /* Compute the Real divider depending on the MCLK output state, with a floating point */
+ if (hi2s->Init.MCLKOutput == I2S_MCLKOUTPUT_ENABLE)
+ {
+ /* MCLK output is enabled */
+ tmp = (uint32_t)((((i2sclk / (256UL >> ispcm)) * 10UL) / hi2s->Init.AudioFreq) + 5UL);
+ }
+ else
+ {
+ /* MCLK output is disabled */
+ tmp = (uint32_t)((((i2sclk / ((32UL >> ispcm) * packetlength)) * 10UL) / hi2s->Init.AudioFreq) + 5UL);
+ }
+
+ /* Remove the flatting point */
+ tmp = tmp / 10UL;
+
+ /* Check the parity of the divider */
+ i2sodd = (uint32_t)(tmp & (uint32_t)1UL);
+
+ /* Compute the i2sdiv prescaler */
+ i2sdiv = (uint32_t)((tmp - i2sodd) / 2UL);
+ }
+ else
+ {
+ /* Set the default values */
+ i2sdiv = 2UL;
+ i2sodd = 0UL;
+ }
+
+ /* Test if the obtain values are forbidden or out of range */
+ if (((i2sodd == 1UL) && (i2sdiv == 1UL)) || (i2sdiv > 0xFFUL))
+ {
+ /* Set the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_PRESCALER);
+ return HAL_ERROR;
+ }
+
+ /* Force i2smod to 1 just to be sure that (2xi2sdiv + i2sodd) is always higher than 0 */
+ if (i2sdiv == 0UL)
+ {
+ i2sodd = 1UL;
+ }
+
+ MODIFY_REG(hi2s->Instance->I2SCFGR, (SPI_I2SCFGR_I2SDIV | SPI_I2SCFGR_ODD),
+ ((i2sdiv << SPI_I2SCFGR_I2SDIV_Pos) | (i2sodd << SPI_I2SCFGR_ODD_Pos)));
+ }
+
+ /*-------------------------- I2Sx I2SCFGR Configuration --------------------*/
+ /* Configure I2SMOD, I2SCFG, I2SSTD, PCMSYNC, DATLEN ,CHLEN ,CKPOL, WSINV, DATAFMT, I2SDIV, ODD and MCKOE bits bits */
+ /* And configure the I2S with the I2S_InitStruct values */
+ MODIFY_REG(hi2s->Instance->I2SCFGR, (SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SCFG | \
+ SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC | \
+ SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN | \
+ SPI_I2SCFGR_CKPOL | SPI_I2SCFGR_WSINV | \
+ SPI_I2SCFGR_DATFMT | SPI_I2SCFGR_MCKOE),
+ (SPI_I2SCFGR_I2SMOD | hi2s->Init.Mode | \
+ hi2s->Init.Standard | hi2s->Init.DataFormat | \
+ hi2s->Init.CPOL | hi2s->Init.WSInversion | \
+ hi2s->Init.Data24BitAlignment | hi2s->Init.MCLKOutput));
+ /*Clear status register*/
+ WRITE_REG(hi2s->Instance->IFCR, 0x0FF8);
+
+ /*---------------------------- I2Sx CFG2 Configuration ----------------------*/
+
+ /* Unlock the AF configuration to configure CFG2 register*/
+ CLEAR_BIT(hi2s->Instance->CR1, SPI_CR1_IOLOCK);
+
+ MODIFY_REG(hi2s->Instance->CFG2, SPI_CFG2_LSBFRST, hi2s->Init.FirstBit);
+
+ /* Insure that AFCNTR is managed only by Master */
+ if (IS_I2S_MASTER(hi2s->Init.Mode))
+ {
+ /* Alternate function GPIOs control */
+ MODIFY_REG(hi2s->Instance->CFG2, SPI_CFG2_AFCNTR, (hi2s->Init.MasterKeepIOState));
+ }
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the I2S peripheral
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_DeInit(I2S_HandleTypeDef *hi2s)
+{
+ /* Check the I2S handle allocation */
+ if (hi2s == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
+
+ hi2s->State = HAL_I2S_STATE_BUSY;
+
+ /* Disable the I2S Peripheral Clock */
+ __HAL_I2S_DISABLE(hi2s);
+
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ if (hi2s->MspDeInitCallback == NULL)
+ {
+ hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ hi2s->MspDeInitCallback(hi2s);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ HAL_I2S_MspDeInit(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State = HAL_I2S_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief I2S MSP Init
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+__weak void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2s);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2S MSP DeInit
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+__weak void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2s);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+/**
+ * @brief Register a User I2S Callback
+ * To be used instead of the weak predefined callback
+ * @param hi2s Pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for the specified I2S.
+ * @param CallbackID ID of the callback to be registered
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_RegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID, pI2S_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hi2s->ErrorCode |= HAL_I2S_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hi2s);
+
+ if (HAL_I2S_STATE_READY == hi2s->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2S_TX_COMPLETE_CB_ID :
+ hi2s->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2S_RX_COMPLETE_CB_ID :
+ hi2s->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2S_TX_HALF_COMPLETE_CB_ID :
+ hi2s->TxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_I2S_RX_HALF_COMPLETE_CB_ID :
+ hi2s->RxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_I2S_ERROR_CB_ID :
+ hi2s->ErrorCallback = pCallback;
+ break;
+
+ case HAL_I2S_MSPINIT_CB_ID :
+ hi2s->MspInitCallback = pCallback;
+ break;
+
+ case HAL_I2S_MSPDEINIT_CB_ID :
+ hi2s->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_I2S_STATE_RESET == hi2s->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2S_MSPINIT_CB_ID :
+ hi2s->MspInitCallback = pCallback;
+ break;
+
+ case HAL_I2S_MSPDEINIT_CB_ID :
+ hi2s->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2s);
+ return status;
+}
+
+/**
+ * @brief Unregister an I2S Callback
+ * I2S callback is redirected to the weak predefined callback
+ * @param hi2s Pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for the specified I2S.
+ * @param CallbackID ID of the callback to be unregistered
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_UnRegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hi2s);
+
+ if (HAL_I2S_STATE_READY == hi2s->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2S_TX_COMPLETE_CB_ID :
+ hi2s->TxCpltCallback = HAL_I2S_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ break;
+
+ case HAL_I2S_RX_COMPLETE_CB_ID :
+ hi2s->RxCpltCallback = HAL_I2S_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ break;
+
+ case HAL_I2S_TX_HALF_COMPLETE_CB_ID :
+ hi2s->TxHalfCpltCallback = HAL_I2S_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ break;
+
+ case HAL_I2S_RX_HALF_COMPLETE_CB_ID :
+ hi2s->RxHalfCpltCallback = HAL_I2S_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ break;
+
+ case HAL_I2S_ERROR_CB_ID :
+ hi2s->ErrorCallback = HAL_I2S_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_I2S_MSPINIT_CB_ID :
+ hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_I2S_MSPDEINIT_CB_ID :
+ hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_I2S_STATE_RESET == hi2s->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2S_MSPINIT_CB_ID :
+ hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_I2S_MSPDEINIT_CB_ID :
+ hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2s);
+ return status;
+}
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+/**
+ * @}
+ */
+
+/** @defgroup I2S_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 I2S data
+ transfers.
+
+ (#) There are two modes of transfer:
+ (++) Blocking mode : The communication is performed in the polling mode.
+ The status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) No-Blocking mode : The communication is performed using Interrupts
+ or DMA. These functions return the status of the transfer startup.
+ The end of the data processing will be indicated through the
+ dedicated I2S IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+
+ (#) Blocking mode functions are :
+ (++) HAL_I2S_Transmit()
+ (++) HAL_I2S_Receive()
+
+ (#) No-Blocking mode functions with Interrupt are :
+ (++) HAL_I2S_Transmit_IT()
+ (++) HAL_I2S_Receive_IT()
+
+ (#) No-Blocking mode functions with DMA are :
+ (++) HAL_I2S_Transmit_DMA()
+ (++) HAL_I2S_Receive_DMA()
+
+ (#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
+ (++) HAL_I2S_TxCpltCallback()
+ (++) HAL_I2S_RxCpltCallback()
+ (++) HAL_I2S_ErrorCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmit an amount of data in blocking mode
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData a 16-bit pointer to data buffer.
+ * @param Size number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @param Timeout Timeout duration
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout)
+{
+#if defined (__GNUC__)
+ __IO uint16_t *ptxdr_16bits = (__IO uint16_t *)(&(hi2s->Instance->TXDR));
+#endif /* __GNUC__ */
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ if (hi2s->State != HAL_I2S_STATE_READY)
+ {
+ __HAL_UNLOCK(hi2s);
+ return HAL_BUSY;
+ }
+
+ /* Set state and reset error code */
+ hi2s->State = HAL_I2S_STATE_BUSY_TX;
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->pTxBuffPtr = pData;
+ hi2s->TxXferSize = Size;
+ hi2s->TxXferCount = Size;
+
+ /* Initialize fields not used in handle to zero */
+ hi2s->pRxBuffPtr = NULL;
+ hi2s->RxXferSize = (uint16_t) 0UL;
+ hi2s->RxXferCount = (uint16_t) 0UL;
+
+ /* Check if the I2S is already enabled */
+ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Start the transfer */
+ SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART);
+
+
+ /* Wait until TXP flag is set */
+ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXP, SET, Timeout) != HAL_OK)
+ {
+ /* Set the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
+ hi2s->State = HAL_I2S_STATE_READY;
+ __HAL_UNLOCK(hi2s);
+ return HAL_ERROR;
+ }
+
+ while (hi2s->TxXferCount > 0UL)
+ {
+ if ((hi2s->Init.DataFormat == I2S_DATAFORMAT_24B) || (hi2s->Init.DataFormat == I2S_DATAFORMAT_32B))
+ {
+ /* Transmit data in 32 Bit mode */
+ hi2s->Instance->TXDR = *((uint32_t *)hi2s->pTxBuffPtr);
+ hi2s->pTxBuffPtr += 2;
+ hi2s->TxXferCount--;
+ }
+ else
+ {
+ /* Transmit data in 16 Bit mode */
+#if defined (__GNUC__)
+ *ptxdr_16bits = *((uint16_t *)hi2s->pTxBuffPtr);
+#else
+ *((__IO uint16_t *)&hi2s->Instance->TXDR) = *((uint16_t *)hi2s->pTxBuffPtr);
+#endif /* __GNUC__ */
+
+ hi2s->pTxBuffPtr++;
+ hi2s->TxXferCount--;
+ }
+
+ /* Wait until TXP flag is set */
+ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXP, SET, Timeout) != HAL_OK)
+ {
+ /* Set the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
+ hi2s->State = HAL_I2S_STATE_READY;
+ __HAL_UNLOCK(hi2s);
+ return HAL_ERROR;
+ }
+
+ /* Check if an underrun occurs */
+ if (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_UDR) == SET)
+ {
+ /* Clear underrun flag */
+ __HAL_I2S_CLEAR_UDRFLAG(hi2s);
+
+ /* Set the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR);
+ }
+ }
+
+ hi2s->State = HAL_I2S_STATE_READY;
+ __HAL_UNLOCK(hi2s);
+ return HAL_OK;
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData a 16-bit pointer to data buffer.
+ * @param Size number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @param Timeout Timeout duration
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @note In I2S Master Receiver mode, just after enabling the peripheral the clock will be generate
+ * in continuous way and as the I2S is not disabled at the end of the I2S transaction.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout)
+{
+#if defined (__GNUC__)
+ __IO uint16_t *prxdr_16bits = (__IO uint16_t *)(&(hi2s->Instance->RXDR));
+#endif /* __GNUC__ */
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ if (hi2s->State != HAL_I2S_STATE_READY)
+ {
+ __HAL_UNLOCK(hi2s);
+ return HAL_BUSY;
+ }
+
+ /* Set state and reset error code */
+ hi2s->State = HAL_I2S_STATE_BUSY_RX;
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->pRxBuffPtr = pData;
+ hi2s->RxXferSize = Size;
+ hi2s->RxXferCount = Size;
+
+ /* Initialize fields not used in handle to zero */
+ hi2s->pTxBuffPtr = NULL;
+ hi2s->TxXferSize = (uint16_t) 0UL;
+ hi2s->TxXferCount = (uint16_t) 0UL;
+
+ /* Check if the I2S is already enabled */
+ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Start the transfer */
+ SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART);
+
+ /* Receive data */
+ while (hi2s->RxXferCount > 0UL)
+ {
+ /* Wait until RXNE flag is set */
+ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXP, SET, Timeout) != HAL_OK)
+ {
+ /* Set the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
+ hi2s->State = HAL_I2S_STATE_READY;
+ __HAL_UNLOCK(hi2s);
+ return HAL_ERROR;
+ }
+
+ if ((hi2s->Init.DataFormat == I2S_DATAFORMAT_24B) || (hi2s->Init.DataFormat == I2S_DATAFORMAT_32B))
+ {
+ /* Receive data in 32 Bit mode */
+ *((uint32_t *)hi2s->pRxBuffPtr) = hi2s->Instance->RXDR;
+ hi2s->pRxBuffPtr += 2;
+ hi2s->RxXferCount--;
+ }
+ else
+ {
+ /* Receive data in 16 Bit mode */
+#if defined (__GNUC__)
+ *((uint16_t *)hi2s->pRxBuffPtr) = *prxdr_16bits;
+#else
+ *((uint16_t *)hi2s->pRxBuffPtr) = *((__IO uint16_t *)&hi2s->Instance->RXDR);
+#endif /* __GNUC__ */
+ hi2s->pRxBuffPtr++;
+ hi2s->RxXferCount--;
+ }
+
+ /* Check if an overrun occurs */
+ if (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_OVR) == SET)
+ {
+ /* Clear overrun flag */
+ __HAL_I2S_CLEAR_OVRFLAG(hi2s);
+
+ /* Set the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR);
+ }
+ }
+
+ hi2s->State = HAL_I2S_STATE_READY;
+ __HAL_UNLOCK(hi2s);
+ return HAL_OK;
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with Interrupt
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData a 16-bit pointer to data buffer.
+ * @param Size number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Transmit_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
+{
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ if (hi2s->State != HAL_I2S_STATE_READY)
+ {
+ __HAL_UNLOCK(hi2s);
+ return HAL_BUSY;
+ }
+
+ /* Set state and reset error code */
+ hi2s->State = HAL_I2S_STATE_BUSY_TX;
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->pTxBuffPtr = (uint16_t *)pData;
+ hi2s->TxXferSize = Size;
+ hi2s->TxXferCount = Size;
+
+ /* Initialize fields not used in handle to zero */
+ hi2s->pRxBuffPtr = NULL;
+ hi2s->RxXferSize = (uint16_t) 0UL;
+ hi2s->RxXferCount = (uint16_t) 0UL;
+
+ /* Set the function for IT treatment */
+ if ((hi2s->Init.DataFormat == I2S_DATAFORMAT_24B) || (hi2s->Init.DataFormat == I2S_DATAFORMAT_32B))
+ {
+ hi2s->TxISR = I2S_Transmit_32Bit_IT;
+ }
+ else
+ {
+ hi2s->TxISR = I2S_Transmit_16Bit_IT;
+ }
+
+ /* Check if the I2S is already enabled */
+ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Enable TXP and UDR interrupt */
+ __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_TXP | I2S_IT_UDR));
+
+ /* Enable TIFRE interrupt if the mode is Slave */
+ if (hi2s->Init.Mode == I2S_MODE_SLAVE_TX)
+ {
+ __HAL_I2S_ENABLE_IT(hi2s, I2S_IT_FRE);
+ }
+
+ /* Start the transfer */
+ SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART);
+
+ __HAL_UNLOCK(hi2s);
+ return HAL_OK;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with Interrupt
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData a 16-bit pointer to the Receive data buffer.
+ * @param Size number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @note It is recommended to use DMA for the I2S receiver to avoid de-synchronization
+ * between Master and Slave otherwise the I2S interrupt should be optimized.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Receive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
+{
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ if (hi2s->State != HAL_I2S_STATE_READY)
+ {
+ __HAL_UNLOCK(hi2s);
+ return HAL_BUSY;
+ }
+
+ /* Set state and reset error code */
+ hi2s->State = HAL_I2S_STATE_BUSY_RX;
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->pRxBuffPtr = pData;
+ hi2s->RxXferSize = Size;
+ hi2s->RxXferCount = Size;
+
+ /* Initialize fields not used in handle to zero */
+ hi2s->pTxBuffPtr = NULL;
+ hi2s->TxXferSize = (uint16_t) 0UL;
+ hi2s->TxXferCount = (uint16_t) 0UL;
+
+ /* Set the function for IT treatment */
+ if ((hi2s->Init.DataFormat == I2S_DATAFORMAT_24B) || (hi2s->Init.DataFormat == I2S_DATAFORMAT_32B))
+ {
+ hi2s->RxISR = I2S_Receive_32Bit_IT;
+ }
+ else
+ {
+ hi2s->RxISR = I2S_Receive_16Bit_IT;
+ }
+
+ /* Check if the I2S is already enabled */
+ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+ /* Enable RXNE and ERR interrupt */
+ __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_RXP | I2S_IT_OVR));
+
+ /* Enable TIFRE interrupt if the mode is Slave */
+ if (hi2s->Init.Mode == I2S_MODE_SLAVE_RX)
+ {
+ __HAL_I2S_ENABLE_IT(hi2s, I2S_IT_FRE);
+ }
+
+ /* Start the transfer */
+ SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART);
+
+ __HAL_UNLOCK(hi2s);
+ return HAL_OK;
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with DMA
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData a 16-bit pointer to the Transmit data buffer.
+ * @param Size number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
+{
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ if (hi2s->State != HAL_I2S_STATE_READY)
+ {
+ __HAL_UNLOCK(hi2s);
+ return HAL_BUSY;
+ }
+
+ /* Set state and reset error code */
+ hi2s->State = HAL_I2S_STATE_BUSY_TX;
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->pTxBuffPtr = pData;
+ hi2s->TxXferSize = Size;
+ hi2s->TxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hi2s->pRxBuffPtr = NULL;
+ hi2s->RxXferSize = (uint16_t)0UL;
+ hi2s->RxXferCount = (uint16_t)0UL;
+
+ /* Set the I2S Tx DMA Half transfer complete callback */
+ hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt;
+
+ /* Set the I2S Tx DMA transfer complete callback */
+ hi2s->hdmatx->XferCpltCallback = I2S_DMATxCplt;
+
+ /* Set the DMA error callback */
+ hi2s->hdmatx->XferErrorCallback = I2S_DMAError;
+
+ /* Enable the Tx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmatx, (uint32_t)hi2s->pTxBuffPtr, (uint32_t)&hi2s->Instance->TXDR, hi2s->TxXferSize))
+ {
+ /* Update SPI error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ __HAL_UNLOCK(hi2s);
+ return HAL_ERROR;
+ }
+
+ /* Check if the I2S Tx request is already enabled */
+ if (HAL_IS_BIT_CLR(hi2s->Instance->CFG1, SPI_CFG1_TXDMAEN))
+ {
+ /* Enable Tx DMA Request */
+ SET_BIT(hi2s->Instance->CFG1, SPI_CFG1_TXDMAEN);
+ }
+
+ /* Check if the I2S is already enabled */
+ if (HAL_IS_BIT_CLR(hi2s->Instance->CR1, SPI_CR1_SPE))
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Start the transfer */
+ SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART);
+
+ __HAL_UNLOCK(hi2s);
+ return HAL_OK;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData a 16-bit pointer to the Receive data buffer.
+ * @param Size number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
+{
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ if (hi2s->State != HAL_I2S_STATE_READY)
+ {
+ __HAL_UNLOCK(hi2s);
+ return HAL_BUSY;
+ }
+
+ /* Set state and reset error code */
+ hi2s->State = HAL_I2S_STATE_BUSY_RX;
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->pRxBuffPtr = pData;
+ hi2s->RxXferSize = Size;
+ hi2s->RxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hi2s->pTxBuffPtr = NULL;
+ hi2s->TxXferSize = (uint16_t)0UL;
+ hi2s->TxXferCount = (uint16_t)0UL;
+
+
+ /* Set the I2S Rx DMA Half transfer complete callback */
+ hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt;
+
+ /* Set the I2S Rx DMA transfer complete callback */
+ hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt;
+
+ /* Set the DMA error callback */
+ hi2s->hdmarx->XferErrorCallback = I2S_DMAError;
+
+ /* Enable the Rx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->RXDR, (uint32_t)hi2s->pRxBuffPtr, hi2s->RxXferSize))
+ {
+ /* Update SPI error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ __HAL_UNLOCK(hi2s);
+ return HAL_ERROR;
+ }
+
+ /* Check if the I2S Rx request is already enabled */
+ if (HAL_IS_BIT_CLR(hi2s->Instance->CFG1, SPI_CFG1_RXDMAEN))
+ {
+ /* Enable Rx DMA Request */
+ SET_BIT(hi2s->Instance->CFG1, SPI_CFG1_RXDMAEN);
+ }
+
+ /* Check if the I2S is already enabled */
+ if (HAL_IS_BIT_CLR(hi2s->Instance->CR1, SPI_CR1_SPE))
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Start the transfer */
+ SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART);
+
+ __HAL_UNLOCK(hi2s);
+ return HAL_OK;
+}
+
+/**
+ * @brief Pauses the audio DMA Stream/Channel playing from the Media.
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_DMAPause(I2S_HandleTypeDef *hi2s)
+{
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ uint32_t tickstart;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+
+ /* Check if the I2S peripheral is in master mode */
+ if (IS_I2S_MASTER(hi2s->Init.Mode))
+ {
+ /* Check if there is a transfer on-going */
+ if (HAL_IS_BIT_SET(hi2s->Instance->CR1, SPI_CR1_CSTART) == 0UL)
+ {
+ /* Set error code to no on going transfer */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_NO_OGT);
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ __HAL_UNLOCK(hi2s);
+ return HAL_ERROR;
+ }
+
+ SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSUSP);
+
+ while (HAL_IS_BIT_SET(hi2s->Instance->CR1, SPI_CR1_CSTART) != 0UL)
+ {
+ if ((((HAL_GetTick() - tickstart) >= I2S_TIMEOUT) && (I2S_TIMEOUT != HAL_MAX_DELAY)) || (I2S_TIMEOUT == 0U))
+ {
+ /* Set the I2S State ready */
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
+ hi2s->State = HAL_I2S_STATE_READY;
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Disable I2S peripheral */
+ __HAL_I2S_DISABLE(hi2s);
+
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Set error code to not supported */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_NOT_SUPPORTED);
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Resumes the audio DMA Stream/Channel playing from the Media.
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_DMAResume(I2S_HandleTypeDef *hi2s)
+{
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ if (hi2s->State != HAL_I2S_STATE_READY)
+ {
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ __HAL_UNLOCK(hi2s);
+ return HAL_ERROR;
+ }
+
+ /* Set state and reset error code */
+ hi2s->State = HAL_I2S_STATE_BUSY;
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+
+ /* Start the transfer */
+ SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the audio DMA Stream/Channel playing from the Media.
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+ /* The Lock is not implemented on this API to allow the user application
+ to call the HAL SPI API under callbacks HAL_I2S_TxCpltCallback() or HAL_I2S_RxCpltCallback()
+ when calling HAL_DMA_Abort() API the DMA TX or RX Transfer complete interrupt is generated
+ and the correspond call back is executed HAL_I2S_TxCpltCallback() or HAL_I2S_RxCpltCallback()
+ */
+
+ /* Disable the I2S Tx/Rx DMA requests */
+ CLEAR_BIT(hi2s->Instance->CFG1, SPI_CFG1_TXDMAEN);
+ CLEAR_BIT(hi2s->Instance->CFG1, SPI_CFG1_RXDMAEN);
+
+ /* Abort the I2S DMA tx Stream/Channel */
+ if (hi2s->hdmatx != NULL)
+ {
+ /* Disable the I2S DMA tx Stream/Channel */
+ if (HAL_OK != HAL_DMA_Abort(hi2s->hdmatx))
+ {
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ }
+ }
+
+ /* Abort the I2S DMA rx Stream/Channel */
+ if (hi2s->hdmarx != NULL)
+ {
+ /* Disable the I2S DMA rx Stream/Channel */
+ if (HAL_OK != HAL_DMA_Abort(hi2s->hdmarx))
+ {
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ }
+ }
+
+ /* Disable I2S peripheral */
+ __HAL_I2S_DISABLE(hi2s);
+
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ return errorcode;
+}
+
+/**
+ * @brief This function handles I2S interrupt request.
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+void HAL_I2S_IRQHandler(I2S_HandleTypeDef *hi2s)
+{
+ uint32_t itsource = hi2s->Instance->IER;
+ uint32_t itflag = hi2s->Instance->SR;
+ uint32_t trigger = itsource & itflag;
+
+ /* I2S in mode Receiver ------------------------------------------------*/
+ if ((I2S_CHECK_FLAG(itflag, I2S_FLAG_OVR) == RESET) && HAL_IS_BIT_SET(trigger, I2S_FLAG_RXP))
+ {
+ hi2s->RxISR(hi2s);
+ }
+
+ /* I2S in mode Transmitter -----------------------------------------------*/
+ if ((I2S_CHECK_FLAG(itflag, I2S_FLAG_UDR) == RESET) && HAL_IS_BIT_SET(trigger, I2S_FLAG_TXP))
+ {
+ hi2s->TxISR(hi2s);
+ }
+
+ /* I2S interrupt error ----------------------------------------------------*/
+ if ((trigger & (I2S_FLAG_OVR| I2S_FLAG_UDR | I2S_FLAG_FRE)) != 0UL)
+ {
+ /* I2S Overrun error interrupt occurred ---------------------------------*/
+ if (I2S_CHECK_FLAG(itflag, I2S_FLAG_OVR) != RESET)
+ {
+ /* Disable RXP and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXP | I2S_IT_ERR));
+
+ /* Set the error code and execute error callback*/
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR);
+ __HAL_I2S_CLEAR_OVRFLAG(hi2s);
+ }
+
+ /* I2S Underrun error interrupt occurred --------------------------------*/
+ if (I2S_CHECK_FLAG(itflag, I2S_FLAG_UDR) != RESET)
+ {
+ /* Disable TXP and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXP | I2S_IT_ERR));
+
+ /* Set the error code and execute error callback*/
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR);
+ __HAL_I2S_CLEAR_UDRFLAG(hi2s);
+ }
+
+ /* I2S Frame error interrupt occurred -----------------------------------*/
+ if (I2S_CHECK_FLAG(itflag, I2S_FLAG_FRE) != RESET)
+ {
+ /* Disable FRE and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_FRE | I2S_IT_ERR));
+
+ /* Set the error code and execute error callback*/
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_FRE);
+ __HAL_I2S_CLEAR_FREFLAG(hi2s);
+ }
+
+ /* Set the I2S State ready */
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Call user error callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->ErrorCallback(hi2s);
+#else
+ HAL_I2S_ErrorCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Tx Transfer Half completed callbacks
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+__weak void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2s);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_TxHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Transfer completed callbacks
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+__weak void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2s);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer half completed callbacks
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+__weak void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2s);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_RxHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callbacks
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+__weak void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2s);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2S error callbacks
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+__weak void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2s);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2S_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the I2S state
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL state
+ */
+HAL_I2S_StateTypeDef HAL_I2S_GetState(I2S_HandleTypeDef *hi2s)
+{
+ return hi2s->State;
+}
+
+/**
+ * @brief Return the I2S error code
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval I2S Error Code
+ */
+uint32_t HAL_I2S_GetError(I2S_HandleTypeDef *hi2s)
+{
+ return hi2s->ErrorCode;
+}
+/**
+ * @}
+ */
+
+
+/**
+ * @brief DMA I2S transmit process complete callback
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
+
+ /* if DMA is configured in DMA_NORMAL Mode */
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ /* Disable Tx DMA Request */
+ CLEAR_BIT(hi2s->Instance->CFG1, SPI_CFG1_TXDMAEN);
+
+ hi2s->TxXferCount = (uint16_t) 0UL;
+ hi2s->State = HAL_I2S_STATE_READY;
+ }
+ /* Call user Tx complete callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->TxCpltCallback(hi2s);
+#else
+ HAL_I2S_TxCpltCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA I2S transmit process half complete callback
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
+
+ /* Call user Tx half complete callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->TxHalfCpltCallback(hi2s);
+#else
+ HAL_I2S_TxHalfCpltCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA I2S receive process complete callback
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
+
+ /* if DMA is configured in DMA_NORMAL Mode */
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ /* Disable Rx DMA Request */
+ CLEAR_BIT(hi2s->Instance->CFG1, SPI_CFG1_RXDMAEN);
+ hi2s->RxXferCount = (uint16_t)0UL;
+ hi2s->State = HAL_I2S_STATE_READY;
+ }
+ /* Call user Rx complete callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->RxCpltCallback(hi2s);
+#else
+ HAL_I2S_RxCpltCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA I2S receive process half complete callback
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
+
+ /* Call user Rx half complete callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->RxHalfCpltCallback(hi2s);
+#else
+ HAL_I2S_RxHalfCpltCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA I2S communication error callback
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void I2S_DMAError(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
+
+ /* Disable Rx and Tx DMA Request */
+ CLEAR_BIT(hi2s->Instance->CFG1, (SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN));
+ hi2s->TxXferCount = (uint16_t) 0UL;
+ hi2s->RxXferCount = (uint16_t) 0UL;
+
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Set the error code and execute error callback*/
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
+ /* Call user error callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->ErrorCallback(hi2s);
+#else
+ HAL_I2S_ErrorCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief Manage the transmission 16-bit in Interrupt context
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+static void I2S_Transmit_16Bit_IT(I2S_HandleTypeDef *hi2s)
+{
+ /* Transmit data */
+#if defined (__GNUC__)
+ __IO uint16_t *ptxdr_16bits = (__IO uint16_t *)(&(hi2s->Instance->TXDR));
+
+ *ptxdr_16bits = *((uint16_t *)hi2s->pTxBuffPtr);
+#else
+ *((__IO uint16_t *)&hi2s->Instance->TXDR) = *((uint16_t *)hi2s->pTxBuffPtr);
+#endif /* __GNUC__ */
+ hi2s->pTxBuffPtr++;
+ hi2s->TxXferCount--;
+
+ if (hi2s->TxXferCount == 0UL)
+ {
+ /* Disable TXE and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXP | I2S_IT_ERR));
+
+ hi2s->State = HAL_I2S_STATE_READY;
+ /* Call user Tx complete callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->TxCpltCallback(hi2s);
+#else
+ HAL_I2S_TxCpltCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Manage the transmission 32-bit in Interrupt context
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+static void I2S_Transmit_32Bit_IT(I2S_HandleTypeDef *hi2s)
+{
+ /* Transmit data */
+ hi2s->Instance->TXDR = *((uint32_t *)hi2s->pTxBuffPtr);
+ hi2s->pTxBuffPtr += 2;
+ hi2s->TxXferCount--;
+
+ if (hi2s->TxXferCount == 0UL)
+ {
+ /* Disable TXE and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXP | I2S_IT_ERR));
+
+ hi2s->State = HAL_I2S_STATE_READY;
+ /* Call user Tx complete callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->TxCpltCallback(hi2s);
+#else
+ HAL_I2S_TxCpltCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Manage the reception 16-bit in Interrupt context
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+static void I2S_Receive_16Bit_IT(I2S_HandleTypeDef *hi2s)
+{
+ /* Receive data */
+#if defined (__GNUC__)
+ __IO uint16_t *prxdr_16bits = (__IO uint16_t *)(&(hi2s->Instance->RXDR));
+
+ *((uint16_t *)hi2s->pRxBuffPtr) = *prxdr_16bits;
+#else
+ *((uint16_t *)hi2s->pRxBuffPtr) = *((__IO uint16_t *)&hi2s->Instance->RXDR);
+#endif /* __GNUC__ */
+ hi2s->pRxBuffPtr++;
+ hi2s->RxXferCount--;
+
+ if (hi2s->RxXferCount == 0UL)
+ {
+ /* Disable RXNE and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXP | I2S_IT_ERR));
+
+ hi2s->State = HAL_I2S_STATE_READY;
+ /* Call user Rx complete callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->RxCpltCallback(hi2s);
+#else
+ HAL_I2S_RxCpltCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Manage the reception 32-bit in Interrupt context
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+static void I2S_Receive_32Bit_IT(I2S_HandleTypeDef *hi2s)
+{
+ /* Receive data */
+ *((uint32_t *)hi2s->pRxBuffPtr) = hi2s->Instance->RXDR;
+ hi2s->pRxBuffPtr += 2;
+ hi2s->RxXferCount--;
+
+ if (hi2s->RxXferCount == 0UL)
+ {
+ /* Disable RXNE and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXP | I2S_IT_ERR));
+
+ hi2s->State = HAL_I2S_STATE_READY;
+ /* Call user Rx complete callback */
+#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1UL)
+ hi2s->RxCpltCallback(hi2s);
+#else
+ HAL_I2S_RxCpltCallback(hi2s);
+#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief This function handles I2S Communication Timeout.
+ * @param hi2s pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param Flag Flag checked
+ * @param State Value of the flag expected
+ * @param Timeout Duration of the timeout
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until flag is set to status*/
+ while (((__HAL_I2S_GET_FLAG(hi2s, Flag)) ? SET : RESET) != State)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) >= Timeout) || (Timeout == 0UL))
+ {
+ /* Set the I2S State ready */
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_I2S_MODULE_ENABLED */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2s_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2s_ex.c
new file mode 100644
index 0000000000..44ed5f6b4d
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_i2s_ex.c
@@ -0,0 +1,28 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_i2s_ex.c
+ * @author MCD Application Team
+ * @brief I2S HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of I2S extension peripheral:
+ * + Extension features Functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### I2S Extension features #####
+ ==============================================================================
+ The I2S Full duplex feature is not supported by this HAL Driver
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_irda.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_irda.c
new file mode 100644
index 0000000000..2d9f808115
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_irda.c
@@ -0,0 +1,2898 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_irda.c
+ * @author MCD Application Team
+ * @brief IRDA HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the IrDA (Infrared Data Association) Peripheral
+ * (IRDA)
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and Errors functions
+ * + Peripheral Control functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The IRDA HAL driver can be used as follows:
+
+ (#) Declare a IRDA_HandleTypeDef handle structure (eg. IRDA_HandleTypeDef hirda).
+ (#) Initialize the IRDA low level resources by implementing the HAL_IRDA_MspInit() API
+ in setting the associated USART or UART in IRDA mode:
+ (++) Enable the USARTx/UARTx interface clock.
+ (++) USARTx/UARTx pins configuration:
+ (+++) Enable the clock for the USARTx/UARTx GPIOs.
+ (+++) Configure these USARTx/UARTx pins (TX as alternate function pull-up, RX as alternate function Input).
+ (++) NVIC configuration if you need to use interrupt process (HAL_IRDA_Transmit_IT()
+ and HAL_IRDA_Receive_IT() APIs):
+ (+++) Configure the USARTx/UARTx interrupt priority.
+ (+++) Enable the NVIC USARTx/UARTx IRQ handle.
+ (+++) The specific IRDA interrupts (Transmission complete interrupt,
+ RXNE interrupt and Error Interrupts) will be managed using the macros
+ __HAL_IRDA_ENABLE_IT() and __HAL_IRDA_DISABLE_IT() inside the transmit and receive process.
+
+ (++) DMA Configuration if you need to use DMA process (HAL_IRDA_Transmit_DMA()
+ and HAL_IRDA_Receive_DMA() APIs):
+ (+++) Declare a DMA handle structure for the Tx/Rx channel.
+ (+++) Enable the DMAx interface clock.
+ (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
+ (+++) Configure the DMA Tx/Rx channel.
+ (+++) Associate the initialized DMA handle to the IRDA DMA Tx/Rx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
+
+ (#) Program the Baud Rate, Word Length and Parity and Mode(Receiver/Transmitter),
+ the normal or low power mode and the clock prescaler in the hirda handle Init structure.
+
+ (#) Initialize the IRDA registers by calling the HAL_IRDA_Init() API:
+ (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
+ by calling the customized HAL_IRDA_MspInit() API.
+
+ -@@- The specific IRDA interrupts (Transmission complete interrupt,
+ RXNE interrupt and Error Interrupts) will be managed using the macros
+ __HAL_IRDA_ENABLE_IT() and __HAL_IRDA_DISABLE_IT() inside the transmit and receive process.
+
+ (#) Three operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Send an amount of data in blocking mode using HAL_IRDA_Transmit()
+ (+) Receive an amount of data in blocking mode using HAL_IRDA_Receive()
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Send an amount of data in non-blocking mode using HAL_IRDA_Transmit_IT()
+ (+) At transmission end of transfer HAL_IRDA_TxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_IRDA_TxCpltCallback()
+ (+) Receive an amount of data in non-blocking mode using HAL_IRDA_Receive_IT()
+ (+) At reception end of transfer HAL_IRDA_RxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_IRDA_RxCpltCallback()
+ (+) In case of transfer Error, HAL_IRDA_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_IRDA_ErrorCallback()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Send an amount of data in non-blocking mode (DMA) using HAL_IRDA_Transmit_DMA()
+ (+) At transmission half of transfer HAL_IRDA_TxHalfCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_IRDA_TxHalfCpltCallback()
+ (+) At transmission end of transfer HAL_IRDA_TxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_IRDA_TxCpltCallback()
+ (+) Receive an amount of data in non-blocking mode (DMA) using HAL_IRDA_Receive_DMA()
+ (+) At reception half of transfer HAL_IRDA_RxHalfCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_IRDA_RxHalfCpltCallback()
+ (+) At reception end of transfer HAL_IRDA_RxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_IRDA_RxCpltCallback()
+ (+) In case of transfer Error, HAL_IRDA_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_IRDA_ErrorCallback()
+
+ *** IRDA HAL driver macros list ***
+ ====================================
+ [..]
+ Below the list of most used macros in IRDA HAL driver.
+
+ (+) __HAL_IRDA_ENABLE: Enable the IRDA peripheral
+ (+) __HAL_IRDA_DISABLE: Disable the IRDA peripheral
+ (+) __HAL_IRDA_GET_FLAG : Check whether the specified IRDA flag is set or not
+ (+) __HAL_IRDA_CLEAR_FLAG : Clear the specified IRDA pending flag
+ (+) __HAL_IRDA_ENABLE_IT: Enable the specified IRDA interrupt
+ (+) __HAL_IRDA_DISABLE_IT: Disable the specified IRDA interrupt
+ (+) __HAL_IRDA_GET_IT_SOURCE: Check whether or not the specified IRDA interrupt is enabled
+
+ [..]
+ (@) You can refer to the IRDA HAL driver header file for more useful macros
+
+ ##### Callback registration #####
+ ==================================
+
+ [..]
+ The compilation define USE_HAL_IRDA_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ [..]
+ Use Function @ref HAL_IRDA_RegisterCallback() to register a user callback.
+ Function @ref HAL_IRDA_RegisterCallback() allows to register following callbacks:
+ (+) TxHalfCpltCallback : Tx Half Complete Callback.
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxHalfCpltCallback : Rx Half Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) AbortCpltCallback : Abort Complete Callback.
+ (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
+ (+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
+ (+) MspInitCallback : IRDA MspInit.
+ (+) MspDeInitCallback : IRDA MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function @ref HAL_IRDA_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function.
+ @ref HAL_IRDA_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxHalfCpltCallback : Tx Half Complete Callback.
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxHalfCpltCallback : Rx Half Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) AbortCpltCallback : Abort Complete Callback.
+ (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
+ (+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
+ (+) MspInitCallback : IRDA MspInit.
+ (+) MspDeInitCallback : IRDA MspDeInit.
+
+ [..]
+ By default, after the @ref HAL_IRDA_Init() and when the state is HAL_IRDA_STATE_RESET
+ all callbacks are set to the corresponding weak (surcharged) functions:
+ examples @ref HAL_IRDA_TxCpltCallback(), @ref HAL_IRDA_RxHalfCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_IRDA_Init()
+ and @ref HAL_IRDA_DeInit() only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_IRDA_Init() and @ref HAL_IRDA_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
+
+ [..]
+ Callbacks can be registered/unregistered in HAL_IRDA_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_IRDA_STATE_READY or HAL_IRDA_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 @ref HAL_IRDA_RegisterCallback() before calling @ref HAL_IRDA_DeInit()
+ or @ref HAL_IRDA_Init() function.
+
+ [..]
+ When The compilation define USE_HAL_IRDA_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available
+ and weak (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup IRDA IRDA
+ * @brief HAL IRDA module driver
+ * @{
+ */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup IRDA_Private_Constants IRDA Private Constants
+ * @{
+ */
+#define IRDA_TEACK_REACK_TIMEOUT 1000U /*!< IRDA TX or RX enable acknowledge time-out value */
+
+#define IRDA_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE \
+ | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE)) /*!< UART or USART CR1 fields of parameters set by IRDA_SetConfig API */
+
+#define USART_BRR_MIN 0x10U /*!< USART BRR minimum authorized value */
+
+#define USART_BRR_MAX 0x0000FFFFU /*!< USART BRR maximum authorized value */
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup IRDA_Private_Macros IRDA Private Macros
+ * @{
+ */
+/** @brief BRR division operation to set BRR register in 16-bit oversampling mode.
+ * @param __PCLK__ IRDA clock source.
+ * @param __BAUD__ Baud rate set by the user.
+ * @param __PRESCALER__ IRDA clock prescaler value.
+ * @retval Division result
+ */
+#define IRDA_DIV_SAMPLING16(__PCLK__, __BAUD__, __PRESCALER__) ((((__PCLK__)/IRDAPrescTable[(__PRESCALER__)])\
+ + ((__BAUD__)/2U)) / (__BAUD__))
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup IRDA_Private_Functions
+ * @{
+ */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+void IRDA_InitCallbacksToDefault(IRDA_HandleTypeDef *hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
+static HAL_StatusTypeDef IRDA_SetConfig(IRDA_HandleTypeDef *hirda);
+static HAL_StatusTypeDef IRDA_CheckIdleState(IRDA_HandleTypeDef *hirda);
+static HAL_StatusTypeDef IRDA_WaitOnFlagUntilTimeout(IRDA_HandleTypeDef *hirda, uint32_t Flag, FlagStatus Status,
+ uint32_t Tickstart, uint32_t Timeout);
+static void IRDA_EndTxTransfer(IRDA_HandleTypeDef *hirda);
+static void IRDA_EndRxTransfer(IRDA_HandleTypeDef *hirda);
+static void IRDA_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void IRDA_DMATransmitHalfCplt(DMA_HandleTypeDef *hdma);
+static void IRDA_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void IRDA_DMAReceiveHalfCplt(DMA_HandleTypeDef *hdma);
+static void IRDA_DMAError(DMA_HandleTypeDef *hdma);
+static void IRDA_DMAAbortOnError(DMA_HandleTypeDef *hdma);
+static void IRDA_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
+static void IRDA_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
+static void IRDA_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
+static void IRDA_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
+static void IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda);
+static void IRDA_EndTransmit_IT(IRDA_HandleTypeDef *hirda);
+static void IRDA_Receive_IT(IRDA_HandleTypeDef *hirda);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup IRDA_Exported_Functions IRDA Exported Functions
+ * @{
+ */
+
+/** @defgroup IRDA_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and Configuration functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to initialize the USARTx
+ in asynchronous IRDA mode.
+ (+) For the asynchronous mode only these parameters can be configured:
+ (++) Baud Rate
+ (++) Word Length
+ (++) Parity: If the parity is enabled, then the MSB bit of the data written
+ in the data register is transmitted but is changed by the parity bit.
+ (++) Power mode
+ (++) Prescaler setting
+ (++) Receiver/transmitter modes
+
+ [..]
+ The HAL_IRDA_Init() API follows the USART asynchronous configuration procedures
+ (details for the procedures are available in reference manual).
+
+@endverbatim
+
+ Depending on the frame length defined by the M1 and M0 bits (7-bit,
+ 8-bit or 9-bit), the possible IRDA frame formats are listed in the
+ following table.
+
+ Table 1. IRDA frame format.
+ +-----------------------------------------------------------------------+
+ | M1 bit | M0 bit | PCE bit | IRDA frame |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 0 | | SB | 8 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 0 | | SB | 9 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 0 | | SB | 7 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | |
+ +-----------------------------------------------------------------------+
+
+ * @{
+ */
+
+/**
+ * @brief Initialize the IRDA mode according to the specified
+ * parameters in the IRDA_InitTypeDef and initialize the associated handle.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_Init(IRDA_HandleTypeDef *hirda)
+{
+ /* Check the IRDA handle allocation */
+ if (hirda == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the USART/UART associated to the IRDA handle */
+ assert_param(IS_IRDA_INSTANCE(hirda->Instance));
+
+ if (hirda->gState == HAL_IRDA_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hirda->Lock = HAL_UNLOCKED;
+
+#if USE_HAL_IRDA_REGISTER_CALLBACKS == 1
+ IRDA_InitCallbacksToDefault(hirda);
+
+ if (hirda->MspInitCallback == NULL)
+ {
+ hirda->MspInitCallback = HAL_IRDA_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hirda->MspInitCallback(hirda);
+#else
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_IRDA_MspInit(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
+ }
+
+ hirda->gState = HAL_IRDA_STATE_BUSY;
+
+ /* Disable the Peripheral to update the configuration registers */
+ __HAL_IRDA_DISABLE(hirda);
+
+ /* Set the IRDA Communication parameters */
+ if (IRDA_SetConfig(hirda) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* In IRDA mode, the following bits must be kept cleared:
+ - LINEN, STOP and CLKEN bits in the USART_CR2 register,
+ - SCEN and HDSEL bits in the USART_CR3 register.*/
+ CLEAR_BIT(hirda->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN | USART_CR2_STOP));
+ CLEAR_BIT(hirda->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL));
+
+ /* set the UART/USART in IRDA mode */
+ hirda->Instance->CR3 |= USART_CR3_IREN;
+
+ /* Enable the Peripheral */
+ __HAL_IRDA_ENABLE(hirda);
+
+ /* TEACK and/or REACK to check before moving hirda->gState and hirda->RxState to Ready */
+ return (IRDA_CheckIdleState(hirda));
+}
+
+/**
+ * @brief DeInitialize the IRDA peripheral.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_DeInit(IRDA_HandleTypeDef *hirda)
+{
+ /* Check the IRDA handle allocation */
+ if (hirda == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the USART/UART associated to the IRDA handle */
+ assert_param(IS_IRDA_INSTANCE(hirda->Instance));
+
+ hirda->gState = HAL_IRDA_STATE_BUSY;
+
+ /* DeInit the low level hardware */
+#if USE_HAL_IRDA_REGISTER_CALLBACKS == 1
+ if (hirda->MspDeInitCallback == NULL)
+ {
+ hirda->MspDeInitCallback = HAL_IRDA_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ hirda->MspDeInitCallback(hirda);
+#else
+ HAL_IRDA_MspDeInit(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
+ /* Disable the Peripheral */
+ __HAL_IRDA_DISABLE(hirda);
+
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+ hirda->gState = HAL_IRDA_STATE_RESET;
+ hirda->RxState = HAL_IRDA_STATE_RESET;
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hirda);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the IRDA MSP.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+__weak void HAL_IRDA_MspInit(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_IRDA_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the IRDA MSP.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+__weak void HAL_IRDA_MspDeInit(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_IRDA_MspDeInit can be implemented in the user file
+ */
+}
+
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User IRDA Callback
+ * To be used instead of the weak predefined callback
+ * @param hirda irda handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_IRDA_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
+ * @arg @ref HAL_IRDA_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_IRDA_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
+ * @arg @ref HAL_IRDA_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_IRDA_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_IRDA_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
+ * @arg @ref HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
+ * @arg @ref HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
+ * @arg @ref HAL_IRDA_MSPINIT_CB_ID MspInit Callback ID
+ * @arg @ref HAL_IRDA_MSPDEINIT_CB_ID MspDeInit Callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_RegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID,
+ pIRDA_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hirda);
+
+ if (hirda->gState == HAL_IRDA_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_IRDA_TX_HALFCOMPLETE_CB_ID :
+ hirda->TxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_IRDA_TX_COMPLETE_CB_ID :
+ hirda->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_IRDA_RX_HALFCOMPLETE_CB_ID :
+ hirda->RxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_IRDA_RX_COMPLETE_CB_ID :
+ hirda->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_IRDA_ERROR_CB_ID :
+ hirda->ErrorCallback = pCallback;
+ break;
+
+ case HAL_IRDA_ABORT_COMPLETE_CB_ID :
+ hirda->AbortCpltCallback = pCallback;
+ break;
+
+ case HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID :
+ hirda->AbortTransmitCpltCallback = pCallback;
+ break;
+
+ case HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID :
+ hirda->AbortReceiveCpltCallback = pCallback;
+ break;
+
+ case HAL_IRDA_MSPINIT_CB_ID :
+ hirda->MspInitCallback = pCallback;
+ break;
+
+ case HAL_IRDA_MSPDEINIT_CB_ID :
+ hirda->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hirda->gState == HAL_IRDA_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_IRDA_MSPINIT_CB_ID :
+ hirda->MspInitCallback = pCallback;
+ break;
+
+ case HAL_IRDA_MSPDEINIT_CB_ID :
+ hirda->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hirda);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an IRDA callback
+ * IRDA callback is redirected to the weak predefined callback
+ * @param hirda irda handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_IRDA_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
+ * @arg @ref HAL_IRDA_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_IRDA_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
+ * @arg @ref HAL_IRDA_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_IRDA_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_IRDA_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
+ * @arg @ref HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
+ * @arg @ref HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
+ * @arg @ref HAL_IRDA_MSPINIT_CB_ID MspInit Callback ID
+ * @arg @ref HAL_IRDA_MSPDEINIT_CB_ID MspDeInit Callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_UnRegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hirda);
+
+ if (HAL_IRDA_STATE_READY == hirda->gState)
+ {
+ switch (CallbackID)
+ {
+ case HAL_IRDA_TX_HALFCOMPLETE_CB_ID :
+ hirda->TxHalfCpltCallback = HAL_IRDA_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ break;
+
+ case HAL_IRDA_TX_COMPLETE_CB_ID :
+ hirda->TxCpltCallback = HAL_IRDA_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ break;
+
+ case HAL_IRDA_RX_HALFCOMPLETE_CB_ID :
+ hirda->RxHalfCpltCallback = HAL_IRDA_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ break;
+
+ case HAL_IRDA_RX_COMPLETE_CB_ID :
+ hirda->RxCpltCallback = HAL_IRDA_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ break;
+
+ case HAL_IRDA_ERROR_CB_ID :
+ hirda->ErrorCallback = HAL_IRDA_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_IRDA_ABORT_COMPLETE_CB_ID :
+ hirda->AbortCpltCallback = HAL_IRDA_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ break;
+
+ case HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID :
+ hirda->AbortTransmitCpltCallback = HAL_IRDA_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
+ break;
+
+ case HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID :
+ hirda->AbortReceiveCpltCallback = HAL_IRDA_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
+ break;
+
+ case HAL_IRDA_MSPINIT_CB_ID :
+ hirda->MspInitCallback = HAL_IRDA_MspInit; /* Legacy weak MspInitCallback */
+ break;
+
+ case HAL_IRDA_MSPDEINIT_CB_ID :
+ hirda->MspDeInitCallback = HAL_IRDA_MspDeInit; /* Legacy weak MspDeInitCallback */
+ break;
+
+ default :
+ /* Update the error code */
+ hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_IRDA_STATE_RESET == hirda->gState)
+ {
+ switch (CallbackID)
+ {
+ case HAL_IRDA_MSPINIT_CB_ID :
+ hirda->MspInitCallback = HAL_IRDA_MspInit;
+ break;
+
+ case HAL_IRDA_MSPDEINIT_CB_ID :
+ hirda->MspDeInitCallback = HAL_IRDA_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hirda);
+
+ return status;
+}
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup IRDA_Exported_Functions_Group2 IO operation functions
+ * @brief IRDA Transmit and Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the IRDA data transfers.
+
+ [..]
+ IrDA is a half duplex communication protocol. If the Transmitter is busy, any data
+ on the IrDA receive line will be ignored by the IrDA decoder and if the Receiver
+ is busy, data on the TX from the USART to IrDA will not be encoded by IrDA.
+ While receiving data, transmission should be avoided as the data to be transmitted
+ could be corrupted.
+
+ [..]
+ (#) There are two modes of transfer:
+ (++) Blocking mode: the communication is performed in polling mode.
+ The HAL status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) Non-Blocking mode: the communication is performed using Interrupts
+ or DMA, these API's return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated IRDA IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+ The HAL_IRDA_TxCpltCallback(), HAL_IRDA_RxCpltCallback() user callbacks
+ will be executed respectively at the end of the Transmit or Receive process
+ The HAL_IRDA_ErrorCallback() user callback will be executed when a communication error is detected
+
+ (#) Blocking mode APIs are :
+ (++) HAL_IRDA_Transmit()
+ (++) HAL_IRDA_Receive()
+
+ (#) Non Blocking mode APIs with Interrupt are :
+ (++) HAL_IRDA_Transmit_IT()
+ (++) HAL_IRDA_Receive_IT()
+ (++) HAL_IRDA_IRQHandler()
+
+ (#) Non Blocking mode functions with DMA are :
+ (++) HAL_IRDA_Transmit_DMA()
+ (++) HAL_IRDA_Receive_DMA()
+ (++) HAL_IRDA_DMAPause()
+ (++) HAL_IRDA_DMAResume()
+ (++) HAL_IRDA_DMAStop()
+
+ (#) A set of Transfer Complete Callbacks are provided in Non Blocking mode:
+ (++) HAL_IRDA_TxHalfCpltCallback()
+ (++) HAL_IRDA_TxCpltCallback()
+ (++) HAL_IRDA_RxHalfCpltCallback()
+ (++) HAL_IRDA_RxCpltCallback()
+ (++) HAL_IRDA_ErrorCallback()
+
+ (#) Non-Blocking mode transfers could be aborted using Abort API's :
+ (++) HAL_IRDA_Abort()
+ (++) HAL_IRDA_AbortTransmit()
+ (++) HAL_IRDA_AbortReceive()
+ (++) HAL_IRDA_Abort_IT()
+ (++) HAL_IRDA_AbortTransmit_IT()
+ (++) HAL_IRDA_AbortReceive_IT()
+
+ (#) For Abort services based on interrupts (HAL_IRDA_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
+ (++) HAL_IRDA_AbortCpltCallback()
+ (++) HAL_IRDA_AbortTransmitCpltCallback()
+ (++) HAL_IRDA_AbortReceiveCpltCallback()
+
+ (#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
+ Errors are handled as follows :
+ (++) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
+ to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
+ Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
+ and HAL_IRDA_ErrorCallback() user callback is executed. Transfer is kept ongoing on IRDA side.
+ If user wants to abort it, Abort services should be called by user.
+ (++) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
+ This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
+ Error code is set to allow user to identify error type, and HAL_IRDA_ErrorCallback() user callback is executed.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Send an amount of data in blocking mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data is handled as a set of u16. In this case, Size must reflect the number
+ * of u16 available through pData.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be sent.
+ * @param Timeout Specify timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_Transmit(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint8_t *pdata8bits;
+ uint16_t *pdata16bits;
+ uint32_t tickstart;
+
+ /* Check that a Tx process is not already ongoing */
+ if (hirda->gState == HAL_IRDA_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hirda);
+
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+ hirda->gState = HAL_IRDA_STATE_BUSY_TX;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ hirda->TxXferSize = Size;
+ hirda->TxXferCount = Size;
+
+ /* In case of 9bits/No Parity transfer, pData needs to be handled as a uint16_t pointer */
+ if ((hirda->Init.WordLength == IRDA_WORDLENGTH_9B) && (hirda->Init.Parity == IRDA_PARITY_NONE))
+ {
+ pdata8bits = NULL;
+ pdata16bits = (uint16_t *) pData; /* Derogation R.11.3 */
+ }
+ else
+ {
+ pdata8bits = pData;
+ pdata16bits = NULL;
+ }
+
+ while (hirda->TxXferCount > 0U)
+ {
+ hirda->TxXferCount--;
+
+ if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ if (pdata8bits == NULL)
+ {
+ hirda->Instance->TDR = (uint16_t)(*pdata16bits & 0x01FFU);
+ pdata16bits++;
+ }
+ else
+ {
+ hirda->Instance->TDR = (uint8_t)(*pdata8bits & 0xFFU);
+ pdata8bits++;
+ }
+ }
+
+ if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* At end of Tx process, restore hirda->gState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of u16. In this case, Size must reflect the number
+ * of u16 available through pData.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be received.
+ * @param Timeout Specify timeout value.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_Receive(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint8_t *pdata8bits;
+ uint16_t *pdata16bits;
+ uint16_t uhMask;
+ uint32_t tickstart;
+
+ /* Check that a Rx process is not already ongoing */
+ if (hirda->RxState == HAL_IRDA_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hirda);
+
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+ hirda->RxState = HAL_IRDA_STATE_BUSY_RX;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ hirda->RxXferSize = Size;
+ hirda->RxXferCount = Size;
+
+ /* Computation of the mask to apply to RDR register
+ of the UART associated to the IRDA */
+ IRDA_MASK_COMPUTATION(hirda);
+ uhMask = hirda->Mask;
+
+ /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
+ if ((hirda->Init.WordLength == IRDA_WORDLENGTH_9B) && (hirda->Init.Parity == IRDA_PARITY_NONE))
+ {
+ pdata8bits = NULL;
+ pdata16bits = (uint16_t *) pData; /* Derogation R.11.3 */
+ }
+ else
+ {
+ pdata8bits = pData;
+ pdata16bits = NULL;
+ }
+
+ /* Check data remaining to be received */
+ while (hirda->RxXferCount > 0U)
+ {
+ hirda->RxXferCount--;
+
+ if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ if (pdata8bits == NULL)
+ {
+ *pdata16bits = (uint16_t)(hirda->Instance->RDR & uhMask);
+ pdata16bits++;
+ }
+ else
+ {
+ *pdata8bits = (uint8_t)(hirda->Instance->RDR & (uint8_t)uhMask);
+ pdata8bits++;
+ }
+ }
+
+ /* At end of Rx process, restore hirda->RxState to Ready */
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in interrupt mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data is handled as a set of u16. In this case, Size must reflect the number
+ * of u16 available through pData.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Tx process is not already ongoing */
+ if (hirda->gState == HAL_IRDA_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hirda);
+
+ hirda->pTxBuffPtr = pData;
+ hirda->TxXferSize = Size;
+ hirda->TxXferCount = Size;
+
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+ hirda->gState = HAL_IRDA_STATE_BUSY_TX;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ /* Enable the IRDA Transmit Data Register Empty Interrupt */
+ SET_BIT(hirda->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in interrupt mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of u16. In this case, Size must reflect the number
+ * of u16 available through pData.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_Receive_IT(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Rx process is not already ongoing */
+ if (hirda->RxState == HAL_IRDA_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hirda);
+
+ hirda->pRxBuffPtr = pData;
+ hirda->RxXferSize = Size;
+ hirda->RxXferCount = Size;
+
+ /* Computation of the mask to apply to the RDR register
+ of the UART associated to the IRDA */
+ IRDA_MASK_COMPUTATION(hirda);
+
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+ hirda->RxState = HAL_IRDA_STATE_BUSY_RX;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ /* Enable the IRDA Parity Error and Data Register not empty Interrupts */
+ SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE);
+
+ /* Enable the IRDA Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in DMA mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data is handled as a set of u16. In this case, Size must reflect the number
+ * of u16 available through pData.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @param pData pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_Transmit_DMA(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Tx process is not already ongoing */
+ if (hirda->gState == HAL_IRDA_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hirda);
+
+ hirda->pTxBuffPtr = pData;
+ hirda->TxXferSize = Size;
+ hirda->TxXferCount = Size;
+
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+ hirda->gState = HAL_IRDA_STATE_BUSY_TX;
+
+ /* Set the IRDA DMA transfer complete callback */
+ hirda->hdmatx->XferCpltCallback = IRDA_DMATransmitCplt;
+
+ /* Set the IRDA DMA half transfer complete callback */
+ hirda->hdmatx->XferHalfCpltCallback = IRDA_DMATransmitHalfCplt;
+
+ /* Set the DMA error callback */
+ hirda->hdmatx->XferErrorCallback = IRDA_DMAError;
+
+ /* Set the DMA abort callback */
+ hirda->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the IRDA transmit DMA channel */
+ if (HAL_DMA_Start_IT(hirda->hdmatx, (uint32_t)hirda->pTxBuffPtr, (uint32_t)&hirda->Instance->TDR, Size) == HAL_OK)
+ {
+ /* Clear the TC flag in the ICR register */
+ __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_CLEAR_TCF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ /* Enable the DMA transfer for transmit request by setting the DMAT bit
+ in the USART CR3 register */
+ SET_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Set error code to DMA */
+ hirda->ErrorCode = HAL_IRDA_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ /* Restore hirda->gState to ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in DMA mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of u16. In this case, Size must reflect the number
+ * of u16 available through pData.
+ * @note When the IRDA parity is enabled (PCE = 1), the received data contains
+ * the parity bit (MSB position).
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_Receive_DMA(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Rx process is not already ongoing */
+ if (hirda->RxState == HAL_IRDA_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hirda);
+
+ hirda->pRxBuffPtr = pData;
+ hirda->RxXferSize = Size;
+
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+ hirda->RxState = HAL_IRDA_STATE_BUSY_RX;
+
+ /* Set the IRDA DMA transfer complete callback */
+ hirda->hdmarx->XferCpltCallback = IRDA_DMAReceiveCplt;
+
+ /* Set the IRDA DMA half transfer complete callback */
+ hirda->hdmarx->XferHalfCpltCallback = IRDA_DMAReceiveHalfCplt;
+
+ /* Set the DMA error callback */
+ hirda->hdmarx->XferErrorCallback = IRDA_DMAError;
+
+ /* Set the DMA abort callback */
+ hirda->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hirda->hdmarx, (uint32_t)&hirda->Instance->RDR, (uint32_t)hirda->pRxBuffPtr, Size) == HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ /* Enable the UART Parity Error Interrupt */
+ SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
+
+ /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the DMA transfer for the receiver request by setting the DMAR bit
+ in the USART CR3 register */
+ SET_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Set error code to DMA */
+ hirda->ErrorCode = HAL_IRDA_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ /* Restore hirda->RxState to ready */
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+/**
+ * @brief Pause the DMA Transfer.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_DMAPause(IRDA_HandleTypeDef *hirda)
+{
+ /* Process Locked */
+ __HAL_LOCK(hirda);
+
+ if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
+ {
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
+ {
+ /* Disable the IRDA DMA Tx request */
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
+ }
+ }
+ if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX)
+ {
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
+ {
+ /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the IRDA DMA Rx request */
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the DMA Transfer.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_DMAResume(IRDA_HandleTypeDef *hirda)
+{
+ /* Process Locked */
+ __HAL_LOCK(hirda);
+
+ if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
+ {
+ /* Enable the IRDA DMA Tx request */
+ SET_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
+ }
+ if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX)
+ {
+ /* Clear the Overrun flag before resuming the Rx transfer*/
+ __HAL_IRDA_CLEAR_OREFLAG(hirda);
+
+ /* Reenable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
+ SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the IRDA DMA Rx request */
+ SET_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the DMA Transfer.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_DMAStop(IRDA_HandleTypeDef *hirda)
+{
+ /* The Lock is not implemented on this API to allow the user application
+ to call the HAL IRDA API under callbacks HAL_IRDA_TxCpltCallback() / HAL_IRDA_RxCpltCallback() /
+ HAL_IRDA_TxHalfCpltCallback / HAL_IRDA_RxHalfCpltCallback:
+ indeed, when HAL_DMA_Abort() API is called, the DMA TX/RX Transfer or Half Transfer complete
+ interrupt is generated if the DMA transfer interruption occurs at the middle or at the end of
+ the stream and the corresponding call back is executed. */
+
+ /* Stop IRDA DMA Tx request if ongoing */
+ if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
+ {
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the IRDA DMA Tx channel */
+ if (hirda->hdmatx != NULL)
+ {
+ if (HAL_DMA_Abort(hirda->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hirda->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hirda->ErrorCode = HAL_IRDA_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ IRDA_EndTxTransfer(hirda);
+ }
+ }
+
+ /* Stop IRDA DMA Rx request if ongoing */
+ if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX)
+ {
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the IRDA DMA Rx channel */
+ if (hirda->hdmarx != NULL)
+ {
+ if (HAL_DMA_Abort(hirda->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hirda->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hirda->ErrorCode = HAL_IRDA_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ IRDA_EndRxTransfer(hirda);
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing transfers (blocking mode).
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable IRDA Interrupts (Tx and Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_Abort(IRDA_HandleTypeDef *hirda)
+{
+ /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the IRDA DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the IRDA DMA Tx channel : use blocking DMA Abort API (no callback) */
+ if (hirda->hdmatx != NULL)
+ {
+ /* Set the IRDA DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ hirda->hdmatx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(hirda->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hirda->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hirda->ErrorCode = HAL_IRDA_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Disable the IRDA DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the IRDA DMA Rx channel : use blocking DMA Abort API (no callback) */
+ if (hirda->hdmarx != NULL)
+ {
+ /* Set the IRDA DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ hirda->hdmarx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(hirda->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hirda->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hirda->ErrorCode = HAL_IRDA_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Tx and Rx transfer counters */
+ hirda->TxXferCount = 0U;
+ hirda->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_CLEAR_OREF | IRDA_CLEAR_NEF | IRDA_CLEAR_PEF | IRDA_CLEAR_FEF);
+
+ /* Restore hirda->gState and hirda->RxState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* Reset Handle ErrorCode to No Error */
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Transmit transfer (blocking mode).
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable IRDA Interrupts (Tx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_AbortTransmit(IRDA_HandleTypeDef *hirda)
+{
+ /* Disable TXEIE and TCIE interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+
+ /* Disable the IRDA DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the IRDA DMA Tx channel : use blocking DMA Abort API (no callback) */
+ if (hirda->hdmatx != NULL)
+ {
+ /* Set the IRDA DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ hirda->hdmatx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(hirda->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hirda->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hirda->ErrorCode = HAL_IRDA_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Tx transfer counter */
+ hirda->TxXferCount = 0U;
+
+ /* Restore hirda->gState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Receive transfer (blocking mode).
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable IRDA Interrupts (Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_AbortReceive(IRDA_HandleTypeDef *hirda)
+{
+ /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the IRDA DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the IRDA DMA Rx channel : use blocking DMA Abort API (no callback) */
+ if (hirda->hdmarx != NULL)
+ {
+ /* Set the IRDA DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ hirda->hdmarx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(hirda->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hirda->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hirda->ErrorCode = HAL_IRDA_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Rx transfer counter */
+ hirda->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_CLEAR_OREF | IRDA_CLEAR_NEF | IRDA_CLEAR_PEF | IRDA_CLEAR_FEF);
+
+ /* Restore hirda->RxState to Ready */
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing transfers (Interrupt mode).
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable IRDA Interrupts (Tx and Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_Abort_IT(IRDA_HandleTypeDef *hirda)
+{
+ uint32_t abortcplt = 1U;
+
+ /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* If DMA Tx and/or DMA Rx Handles are associated to IRDA Handle, DMA Abort complete callbacks should be initialised
+ before any call to DMA Abort functions */
+ /* DMA Tx Handle is valid */
+ if (hirda->hdmatx != NULL)
+ {
+ /* Set DMA Abort Complete callback if IRDA DMA Tx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
+ {
+ hirda->hdmatx->XferAbortCallback = IRDA_DMATxAbortCallback;
+ }
+ else
+ {
+ hirda->hdmatx->XferAbortCallback = NULL;
+ }
+ }
+ /* DMA Rx Handle is valid */
+ if (hirda->hdmarx != NULL)
+ {
+ /* Set DMA Abort Complete callback if IRDA DMA Rx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
+ {
+ hirda->hdmarx->XferAbortCallback = IRDA_DMARxAbortCallback;
+ }
+ else
+ {
+ hirda->hdmarx->XferAbortCallback = NULL;
+ }
+ }
+
+ /* Disable the IRDA DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
+ {
+ /* Disable DMA Tx at UART level */
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the IRDA DMA Tx channel : use non blocking DMA Abort API (callback) */
+ if (hirda->hdmatx != NULL)
+ {
+ /* IRDA Tx DMA Abort callback has already been initialised :
+ will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hirda->hdmatx) != HAL_OK)
+ {
+ hirda->hdmatx->XferAbortCallback = NULL;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+
+ /* Disable the IRDA DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the IRDA DMA Rx channel : use non blocking DMA Abort API (callback) */
+ if (hirda->hdmarx != NULL)
+ {
+ /* IRDA Rx DMA Abort callback has already been initialised :
+ will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK)
+ {
+ hirda->hdmarx->XferAbortCallback = NULL;
+ abortcplt = 1U;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+
+ /* if no DMA abort complete callback execution is required => call user Abort Complete callback */
+ if (abortcplt == 1U)
+ {
+ /* Reset Tx and Rx transfer counters */
+ hirda->TxXferCount = 0U;
+ hirda->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_CLEAR_OREF | IRDA_CLEAR_NEF | IRDA_CLEAR_PEF | IRDA_CLEAR_FEF);
+
+ /* Restore hirda->gState and hirda->RxState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort complete callback */
+ hirda->AbortCpltCallback(hirda);
+#else
+ /* Call legacy weak Abort complete callback */
+ HAL_IRDA_AbortCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Transmit transfer (Interrupt mode).
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable IRDA Interrupts (Tx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_AbortTransmit_IT(IRDA_HandleTypeDef *hirda)
+{
+ /* Disable TXEIE and TCIE interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+
+ /* Disable the IRDA DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the IRDA DMA Tx channel : use non blocking DMA Abort API (callback) */
+ if (hirda->hdmatx != NULL)
+ {
+ /* Set the IRDA DMA Abort callback :
+ will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
+ hirda->hdmatx->XferAbortCallback = IRDA_DMATxOnlyAbortCallback;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hirda->hdmatx) != HAL_OK)
+ {
+ /* Call Directly hirda->hdmatx->XferAbortCallback function in case of error */
+ hirda->hdmatx->XferAbortCallback(hirda->hdmatx);
+ }
+ }
+ else
+ {
+ /* Reset Tx transfer counter */
+ hirda->TxXferCount = 0U;
+
+ /* Restore hirda->gState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Transmit Complete Callback */
+ hirda->AbortTransmitCpltCallback(hirda);
+#else
+ /* Call legacy weak Abort Transmit Complete Callback */
+ HAL_IRDA_AbortTransmitCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+ /* Reset Tx transfer counter */
+ hirda->TxXferCount = 0U;
+
+ /* Restore hirda->gState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Transmit Complete Callback */
+ hirda->AbortTransmitCpltCallback(hirda);
+#else
+ /* Call legacy weak Abort Transmit Complete Callback */
+ HAL_IRDA_AbortTransmitCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Receive transfer (Interrupt mode).
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable IRDA Interrupts (Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IRDA_AbortReceive_IT(IRDA_HandleTypeDef *hirda)
+{
+ /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the IRDA DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the IRDA DMA Rx channel : use non blocking DMA Abort API (callback) */
+ if (hirda->hdmarx != NULL)
+ {
+ /* Set the IRDA DMA Abort callback :
+ will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
+ hirda->hdmarx->XferAbortCallback = IRDA_DMARxOnlyAbortCallback;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hirda->hdmarx->XferAbortCallback function in case of error */
+ hirda->hdmarx->XferAbortCallback(hirda->hdmarx);
+ }
+ }
+ else
+ {
+ /* Reset Rx transfer counter */
+ hirda->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_CLEAR_OREF | IRDA_CLEAR_NEF | IRDA_CLEAR_PEF | IRDA_CLEAR_FEF);
+
+ /* Restore hirda->RxState to Ready */
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Receive Complete Callback */
+ hirda->AbortReceiveCpltCallback(hirda);
+#else
+ /* Call legacy weak Abort Receive Complete Callback */
+ HAL_IRDA_AbortReceiveCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+ /* Reset Rx transfer counter */
+ hirda->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_CLEAR_OREF | IRDA_CLEAR_NEF | IRDA_CLEAR_PEF | IRDA_CLEAR_FEF);
+
+ /* Restore hirda->RxState to Ready */
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Receive Complete Callback */
+ hirda->AbortReceiveCpltCallback(hirda);
+#else
+ /* Call legacy weak Abort Receive Complete Callback */
+ HAL_IRDA_AbortReceiveCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle IRDA interrupt request.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+void HAL_IRDA_IRQHandler(IRDA_HandleTypeDef *hirda)
+{
+ uint32_t isrflags = READ_REG(hirda->Instance->ISR);
+ uint32_t cr1its = READ_REG(hirda->Instance->CR1);
+ uint32_t cr3its;
+ uint32_t errorflags;
+ uint32_t errorcode;
+
+ /* If no error occurs */
+ errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE));
+ if (errorflags == 0U)
+ {
+ /* IRDA in mode Receiver ---------------------------------------------------*/
+ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U) && ((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U))
+ {
+ IRDA_Receive_IT(hirda);
+ return;
+ }
+ }
+
+ /* If some errors occur */
+ cr3its = READ_REG(hirda->Instance->CR3);
+ if ((errorflags != 0U)
+ && (((cr3its & USART_CR3_EIE) != 0U)
+ || ((cr1its & (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)) != 0U)))
+ {
+ /* IRDA parity error interrupt occurred -------------------------------------*/
+ if (((isrflags & USART_ISR_PE) != 0U) && ((cr1its & USART_CR1_PEIE) != 0U))
+ {
+ __HAL_IRDA_CLEAR_IT(hirda, IRDA_CLEAR_PEF);
+
+ hirda->ErrorCode |= HAL_IRDA_ERROR_PE;
+ }
+
+ /* IRDA frame error interrupt occurred --------------------------------------*/
+ if (((isrflags & USART_ISR_FE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
+ {
+ __HAL_IRDA_CLEAR_IT(hirda, IRDA_CLEAR_FEF);
+
+ hirda->ErrorCode |= HAL_IRDA_ERROR_FE;
+ }
+
+ /* IRDA noise error interrupt occurred --------------------------------------*/
+ if (((isrflags & USART_ISR_NE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
+ {
+ __HAL_IRDA_CLEAR_IT(hirda, IRDA_CLEAR_NEF);
+
+ hirda->ErrorCode |= HAL_IRDA_ERROR_NE;
+ }
+
+ /* IRDA Over-Run interrupt occurred -----------------------------------------*/
+ if (((isrflags & USART_ISR_ORE) != 0U) &&
+ (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) || ((cr3its & USART_CR3_EIE) != 0U)))
+ {
+ __HAL_IRDA_CLEAR_IT(hirda, IRDA_CLEAR_OREF);
+
+ hirda->ErrorCode |= HAL_IRDA_ERROR_ORE;
+ }
+
+ /* Call IRDA Error Call back function if need be --------------------------*/
+ if (hirda->ErrorCode != HAL_IRDA_ERROR_NONE)
+ {
+ /* IRDA in mode Receiver ---------------------------------------------------*/
+ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U) && ((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U))
+ {
+ IRDA_Receive_IT(hirda);
+ }
+
+ /* If Overrun error occurs, or if any error occurs in DMA mode reception,
+ consider error as blocking */
+ errorcode = hirda->ErrorCode;
+ if ((HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR)) ||
+ ((errorcode & HAL_IRDA_ERROR_ORE) != 0U))
+ {
+ /* Blocking error : transfer is aborted
+ Set the IRDA state ready to be able to start again the process,
+ Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
+ IRDA_EndRxTransfer(hirda);
+
+ /* Disable the IRDA DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the IRDA DMA Rx channel */
+ if (hirda->hdmarx != NULL)
+ {
+ /* Set the IRDA DMA Abort callback :
+ will lead to call HAL_IRDA_ErrorCallback() at end of DMA abort procedure */
+ hirda->hdmarx->XferAbortCallback = IRDA_DMAAbortOnError;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hirda->hdmarx->XferAbortCallback function in case of error */
+ hirda->hdmarx->XferAbortCallback(hirda->hdmarx);
+ }
+ }
+ else
+ {
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hirda->ErrorCallback(hirda);
+#else
+ /* Call legacy weak user error callback */
+ HAL_IRDA_ErrorCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hirda->ErrorCallback(hirda);
+#else
+ /* Call legacy weak user error callback */
+ HAL_IRDA_ErrorCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+ /* Non Blocking error : transfer could go on.
+ Error is notified to user through user error callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hirda->ErrorCallback(hirda);
+#else
+ /* Call legacy weak user error callback */
+ HAL_IRDA_ErrorCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+ }
+ }
+ return;
+
+ } /* End if some error occurs */
+
+ /* IRDA in mode Transmitter ------------------------------------------------*/
+ if (((isrflags & USART_ISR_TXE_TXFNF) != 0U) && ((cr1its & USART_CR1_TXEIE_TXFNFIE) != 0U))
+ {
+ IRDA_Transmit_IT(hirda);
+ return;
+ }
+
+ /* IRDA in mode Transmitter (transmission end) -----------------------------*/
+ if (((isrflags & USART_ISR_TC) != 0U) && ((cr1its & USART_CR1_TCIE) != 0U))
+ {
+ IRDA_EndTransmit_IT(hirda);
+ return;
+ }
+
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+__weak void HAL_IRDA_TxCpltCallback(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IRDA_TxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified USART module.
+ * @retval None
+ */
+__weak void HAL_IRDA_TxHalfCpltCallback(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IRDA_TxHalfCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+__weak void HAL_IRDA_RxCpltCallback(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IRDA_RxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Rx Half Transfer complete callback.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+__weak void HAL_IRDA_RxHalfCpltCallback(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IRDA_RxHalfCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief IRDA error callback.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+__weak void HAL_IRDA_ErrorCallback(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IRDA_ErrorCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief IRDA Abort Complete callback.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+__weak void HAL_IRDA_AbortCpltCallback(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IRDA_AbortCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief IRDA Abort Complete callback.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+__weak void HAL_IRDA_AbortTransmitCpltCallback(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IRDA_AbortTransmitCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief IRDA Abort Receive Complete callback.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+__weak void HAL_IRDA_AbortReceiveCpltCallback(IRDA_HandleTypeDef *hirda)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hirda);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IRDA_AbortReceiveCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup IRDA_Exported_Functions_Group4 Peripheral State and Error functions
+ * @brief IRDA State and Errors functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Error functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to return the State of IrDA
+ communication process and also return Peripheral Errors occurred during communication process
+ (+) HAL_IRDA_GetState() API can be helpful to check in run-time the state
+ of the IRDA peripheral handle.
+ (+) HAL_IRDA_GetError() checks in run-time errors that could occur during
+ communication.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the IRDA handle state.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval HAL state
+ */
+HAL_IRDA_StateTypeDef HAL_IRDA_GetState(IRDA_HandleTypeDef *hirda)
+{
+ /* Return IRDA handle state */
+ uint32_t temp1;
+ uint32_t temp2;
+ temp1 = (uint32_t)hirda->gState;
+ temp2 = (uint32_t)hirda->RxState;
+
+ return (HAL_IRDA_StateTypeDef)(temp1 | temp2);
+}
+
+/**
+ * @brief Return the IRDA handle error code.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval IRDA Error Code
+ */
+uint32_t HAL_IRDA_GetError(IRDA_HandleTypeDef *hirda)
+{
+ return hirda->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup IRDA_Private_Functions IRDA Private Functions
+ * @{
+ */
+
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Initialize the callbacks to their default values.
+ * @param hirda IRDA handle.
+ * @retval none
+ */
+void IRDA_InitCallbacksToDefault(IRDA_HandleTypeDef *hirda)
+{
+ /* Init the IRDA Callback settings */
+ hirda->TxHalfCpltCallback = HAL_IRDA_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ hirda->TxCpltCallback = HAL_IRDA_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ hirda->RxHalfCpltCallback = HAL_IRDA_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ hirda->RxCpltCallback = HAL_IRDA_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ hirda->ErrorCallback = HAL_IRDA_ErrorCallback; /* Legacy weak ErrorCallback */
+ hirda->AbortCpltCallback = HAL_IRDA_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ hirda->AbortTransmitCpltCallback = HAL_IRDA_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
+ hirda->AbortReceiveCpltCallback = HAL_IRDA_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
+
+}
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
+
+/**
+ * @brief Configure the IRDA peripheral.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef IRDA_SetConfig(IRDA_HandleTypeDef *hirda)
+{
+ uint32_t tmpreg;
+ IRDA_ClockSourceTypeDef clocksource;
+ HAL_StatusTypeDef ret = HAL_OK;
+ const uint16_t IRDAPrescTable[12] = {1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U};
+ PLL2_ClocksTypeDef pll2_clocks;
+ PLL3_ClocksTypeDef pll3_clocks;
+ uint32_t pclk;
+
+ /* Check the communication parameters */
+ assert_param(IS_IRDA_BAUDRATE(hirda->Init.BaudRate));
+ assert_param(IS_IRDA_WORD_LENGTH(hirda->Init.WordLength));
+ assert_param(IS_IRDA_PARITY(hirda->Init.Parity));
+ assert_param(IS_IRDA_TX_RX_MODE(hirda->Init.Mode));
+ assert_param(IS_IRDA_PRESCALER(hirda->Init.Prescaler));
+ assert_param(IS_IRDA_POWERMODE(hirda->Init.PowerMode));
+ assert_param(IS_IRDA_CLOCKPRESCALER(hirda->Init.ClockPrescaler));
+
+ /*-------------------------- USART CR1 Configuration -----------------------*/
+ /* Configure the IRDA Word Length, Parity and transfer Mode:
+ Set the M bits according to hirda->Init.WordLength value
+ Set PCE and PS bits according to hirda->Init.Parity value
+ Set TE and RE bits according to hirda->Init.Mode value */
+ tmpreg = (uint32_t)hirda->Init.WordLength | hirda->Init.Parity | hirda->Init.Mode ;
+
+ MODIFY_REG(hirda->Instance->CR1, IRDA_CR1_FIELDS, tmpreg);
+
+ /*-------------------------- USART CR3 Configuration -----------------------*/
+ MODIFY_REG(hirda->Instance->CR3, USART_CR3_IRLP, hirda->Init.PowerMode);
+
+ /*--------------------- USART clock PRESC Configuration ----------------*/
+ /* Configure
+ * - IRDA Clock Prescaler: set PRESCALER according to hirda->Init.ClockPrescaler value */
+ MODIFY_REG(hirda->Instance->PRESC, USART_PRESC_PRESCALER, hirda->Init.ClockPrescaler);
+
+ /*-------------------------- USART GTPR Configuration ----------------------*/
+ MODIFY_REG(hirda->Instance->GTPR, (uint16_t)USART_GTPR_PSC, (uint16_t)hirda->Init.Prescaler);
+
+ /*-------------------------- USART BRR Configuration -----------------------*/
+ IRDA_GETCLOCKSOURCE(hirda, clocksource);
+ tmpreg = 0U;
+ switch (clocksource)
+ {
+ case IRDA_CLOCKSOURCE_D2PCLK1:
+ pclk = HAL_RCC_GetPCLK1Freq();
+ tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(pclk, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ break;
+ case IRDA_CLOCKSOURCE_D2PCLK2:
+ pclk = HAL_RCC_GetPCLK2Freq();
+ tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(pclk, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ break;
+ case IRDA_CLOCKSOURCE_PLL2Q:
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(pll2_clocks.PLL2_Q_Frequency, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ break;
+ case IRDA_CLOCKSOURCE_PLL3Q:
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(pll3_clocks.PLL3_Q_Frequency, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ break;
+ case IRDA_CLOCKSOURCE_CSI:
+ tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(CSI_VALUE, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ break;
+ case IRDA_CLOCKSOURCE_HSI:
+ tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16(HSI_VALUE, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ break;
+ case IRDA_CLOCKSOURCE_LSE:
+ tmpreg = (uint16_t)(IRDA_DIV_SAMPLING16((uint32_t)LSE_VALUE, hirda->Init.BaudRate, hirda->Init.ClockPrescaler));
+ break;
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ /* USARTDIV must be greater than or equal to 0d16 */
+ if ((tmpreg >= USART_BRR_MIN) && (tmpreg <= USART_BRR_MAX))
+ {
+ hirda->Instance->BRR = tmpreg;
+ }
+ else
+ {
+ ret = HAL_ERROR;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Check the IRDA Idle State.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef IRDA_CheckIdleState(IRDA_HandleTypeDef *hirda)
+{
+ uint32_t tickstart;
+
+ /* Initialize the IRDA ErrorCode */
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Check if the Transmitter is enabled */
+ if ((hirda->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE)
+ {
+ /* Wait until TEACK flag is set */
+ if (IRDA_WaitOnFlagUntilTimeout(hirda, USART_ISR_TEACK, RESET, tickstart, IRDA_TEACK_REACK_TIMEOUT) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Check if the Receiver is enabled */
+ if ((hirda->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE)
+ {
+ /* Wait until REACK flag is set */
+ if (IRDA_WaitOnFlagUntilTimeout(hirda, USART_ISR_REACK, RESET, tickstart, IRDA_TEACK_REACK_TIMEOUT) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Initialize the IRDA state*/
+ hirda->gState = HAL_IRDA_STATE_READY;
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle IRDA Communication Timeout.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @param Flag Specifies the IRDA flag to check.
+ * @param Status Flag status (SET or RESET)
+ * @param Tickstart Tick start value
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef IRDA_WaitOnFlagUntilTimeout(IRDA_HandleTypeDef *hirda, uint32_t Flag, FlagStatus Status,
+ uint32_t Tickstart, uint32_t Timeout)
+{
+ /* Wait until flag is set */
+ while ((__HAL_IRDA_GET_FLAG(hirda, Flag) ? SET : RESET) == Status)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE));
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ hirda->gState = HAL_IRDA_STATE_READY;
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hirda);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+
+/**
+ * @brief End ongoing Tx transfer on IRDA peripheral (following error detection or Transmit completion).
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+static void IRDA_EndTxTransfer(IRDA_HandleTypeDef *hirda)
+{
+ /* Disable TXEIE and TCIE interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+
+ /* At end of Tx process, restore hirda->gState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+}
+
+
+/**
+ * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion).
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+static void IRDA_EndRxTransfer(IRDA_HandleTypeDef *hirda)
+{
+ /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* At end of Rx process, restore hirda->RxState to Ready */
+ hirda->RxState = HAL_IRDA_STATE_READY;
+}
+
+
+/**
+ * @brief DMA IRDA 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 IRDA_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)(hdma->Parent);
+
+ /* DMA Normal mode */
+ if (hdma->Init.Mode != DMA_CIRCULAR)
+ {
+ hirda->TxXferCount = 0U;
+
+ /* Disable the DMA transfer for transmit request by resetting the DMAT bit
+ in the IRDA CR3 register */
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
+
+ /* Enable the IRDA Transmit Complete Interrupt */
+ SET_BIT(hirda->Instance->CR1, USART_CR1_TCIE);
+ }
+ /* DMA Circular mode */
+ else
+ {
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx complete callback */
+ hirda->TxCpltCallback(hirda);
+#else
+ /* Call legacy weak Tx complete callback */
+ HAL_IRDA_TxCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+ }
+
+}
+
+/**
+ * @brief DMA IRDA 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 IRDA_DMATransmitHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)(hdma->Parent);
+
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Half complete callback */
+ hirda->TxHalfCpltCallback(hirda);
+#else
+ /* Call legacy weak Tx complete callback */
+ HAL_IRDA_TxHalfCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief DMA IRDA 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 IRDA_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)(hdma->Parent);
+
+ /* DMA Normal mode */
+ if (hdma->Init.Mode != DMA_CIRCULAR)
+ {
+ hirda->RxXferCount = 0U;
+
+ /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the DMA transfer for the receiver request by resetting the DMAR bit
+ in the IRDA CR3 register */
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
+
+ /* At end of Rx process, restore hirda->RxState to Ready */
+ hirda->RxState = HAL_IRDA_STATE_READY;
+ }
+
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx complete callback */
+ hirda->RxCpltCallback(hirda);
+#else
+ /* Call legacy weak Rx complete callback */
+ HAL_IRDA_RxCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA IRDA 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 IRDA_DMAReceiveHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)(hdma->Parent);
+
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /*Call registered Rx Half complete callback*/
+ hirda->RxHalfCpltCallback(hirda);
+#else
+ /* Call legacy weak Rx Half complete callback */
+ HAL_IRDA_RxHalfCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief DMA IRDA 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 IRDA_DMAError(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)(hdma->Parent);
+
+ /* Stop IRDA DMA Tx request if ongoing */
+ if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
+ {
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
+ {
+ hirda->TxXferCount = 0U;
+ IRDA_EndTxTransfer(hirda);
+ }
+ }
+
+ /* Stop IRDA DMA Rx request if ongoing */
+ if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX)
+ {
+ if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
+ {
+ hirda->RxXferCount = 0U;
+ IRDA_EndRxTransfer(hirda);
+ }
+ }
+
+ hirda->ErrorCode |= HAL_IRDA_ERROR_DMA;
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hirda->ErrorCallback(hirda);
+#else
+ /* Call legacy weak user error callback */
+ HAL_IRDA_ErrorCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief DMA IRDA communication abort callback, when initiated by HAL services on Error
+ * (To be called at end of DMA Abort procedure following error occurrence).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void IRDA_DMAAbortOnError(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)(hdma->Parent);
+ hirda->RxXferCount = 0U;
+ hirda->TxXferCount = 0U;
+
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hirda->ErrorCallback(hirda);
+#else
+ /* Call legacy weak user error callback */
+ HAL_IRDA_ErrorCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief DMA IRDA Tx communication abort callback, when initiated by user
+ * (To be called at end of DMA Tx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Rx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void IRDA_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)(hdma->Parent);
+
+ hirda->hdmatx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (hirda->hdmarx != NULL)
+ {
+ if (hirda->hdmarx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
+ hirda->TxXferCount = 0U;
+ hirda->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_CLEAR_OREF | IRDA_CLEAR_NEF | IRDA_CLEAR_PEF | IRDA_CLEAR_FEF);
+
+ /* Restore hirda->gState and hirda->RxState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort complete callback */
+ hirda->AbortCpltCallback(hirda);
+#else
+ /* Call legacy weak Abort complete callback */
+ HAL_IRDA_AbortCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+}
+
+
+/**
+ * @brief DMA IRDA Rx communication abort callback, when initiated by user
+ * (To be called at end of DMA Rx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Tx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void IRDA_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)(hdma->Parent);
+
+ hirda->hdmarx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (hirda->hdmatx != NULL)
+ {
+ if (hirda->hdmatx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
+ hirda->TxXferCount = 0U;
+ hirda->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_CLEAR_OREF | IRDA_CLEAR_NEF | IRDA_CLEAR_PEF | IRDA_CLEAR_FEF);
+
+ /* Restore hirda->gState and hirda->RxState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort complete callback */
+ hirda->AbortCpltCallback(hirda);
+#else
+ /* Call legacy weak Abort complete callback */
+ HAL_IRDA_AbortCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+}
+
+
+/**
+ * @brief DMA IRDA Tx communication abort callback, when initiated by user by a call to
+ * HAL_IRDA_AbortTransmit_IT API (Abort only Tx transfer)
+ * (This callback is executed at end of DMA Tx Abort procedure following user abort request,
+ * and leads to user Tx Abort Complete callback execution).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void IRDA_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)(hdma->Parent);
+
+ hirda->TxXferCount = 0U;
+
+ /* Restore hirda->gState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Transmit Complete Callback */
+ hirda->AbortTransmitCpltCallback(hirda);
+#else
+ /* Call legacy weak Abort Transmit Complete Callback */
+ HAL_IRDA_AbortTransmitCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief DMA IRDA Rx communication abort callback, when initiated by user by a call to
+ * HAL_IRDA_AbortReceive_IT API (Abort only Rx transfer)
+ * (This callback is executed at end of DMA Rx Abort procedure following user abort request,
+ * and leads to user Rx Abort Complete callback execution).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void IRDA_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ hirda->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_CLEAR_OREF | IRDA_CLEAR_NEF | IRDA_CLEAR_PEF | IRDA_CLEAR_FEF);
+
+ /* Restore hirda->RxState to Ready */
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Receive Complete Callback */
+ hirda->AbortReceiveCpltCallback(hirda);
+#else
+ /* Call legacy weak Abort Receive Complete Callback */
+ HAL_IRDA_AbortReceiveCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief Send an amount of data in interrupt mode.
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_IRDA_Transmit_IT().
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+static void IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda)
+{
+ uint16_t *tmp;
+
+ /* Check that a Tx process is ongoing */
+ if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
+ {
+ if (hirda->TxXferCount == 0U)
+ {
+ /* Disable the IRDA Transmit Data Register Empty Interrupt */
+ CLEAR_BIT(hirda->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
+
+ /* Enable the IRDA Transmit Complete Interrupt */
+ SET_BIT(hirda->Instance->CR1, USART_CR1_TCIE);
+ }
+ else
+ {
+ if ((hirda->Init.WordLength == IRDA_WORDLENGTH_9B) && (hirda->Init.Parity == IRDA_PARITY_NONE))
+ {
+ tmp = (uint16_t *) hirda->pTxBuffPtr; /* Derogation R.11.3 */
+ hirda->Instance->TDR = (uint16_t)(*tmp & 0x01FFU);
+ hirda->pTxBuffPtr += 2U;
+ }
+ else
+ {
+ hirda->Instance->TDR = (uint8_t)(*hirda->pTxBuffPtr & 0xFFU);
+ hirda->pTxBuffPtr++;
+ }
+ hirda->TxXferCount--;
+ }
+ }
+}
+
+/**
+ * @brief Wrap up transmission in non-blocking mode.
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+static void IRDA_EndTransmit_IT(IRDA_HandleTypeDef *hirda)
+{
+ /* Disable the IRDA Transmit Complete Interrupt */
+ CLEAR_BIT(hirda->Instance->CR1, USART_CR1_TCIE);
+
+ /* Tx process is ended, restore hirda->gState to Ready */
+ hirda->gState = HAL_IRDA_STATE_READY;
+
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx complete callback */
+ hirda->TxCpltCallback(hirda);
+#else
+ /* Call legacy weak Tx complete callback */
+ HAL_IRDA_TxCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief Receive an amount of data in interrupt mode.
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_IRDA_Receive_IT()
+ * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
+ * the configuration information for the specified IRDA module.
+ * @retval None
+ */
+static void IRDA_Receive_IT(IRDA_HandleTypeDef *hirda)
+{
+ uint16_t *tmp;
+ uint16_t uhMask = hirda->Mask;
+ uint16_t uhdata;
+
+ /* Check that a Rx process is ongoing */
+ if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX)
+ {
+ uhdata = (uint16_t) READ_REG(hirda->Instance->RDR);
+ if ((hirda->Init.WordLength == IRDA_WORDLENGTH_9B) && (hirda->Init.Parity == IRDA_PARITY_NONE))
+ {
+ tmp = (uint16_t *) hirda->pRxBuffPtr; /* Derogation R.11.3 */
+ *tmp = (uint16_t)(uhdata & uhMask);
+ hirda->pRxBuffPtr += 2U;
+ }
+ else
+ {
+ *hirda->pRxBuffPtr = (uint8_t)(uhdata & (uint8_t)uhMask);
+ hirda->pRxBuffPtr++;
+ }
+
+ hirda->RxXferCount--;
+ if (hirda->RxXferCount == 0U)
+ {
+ /* Disable the IRDA Parity Error Interrupt and RXNE interrupt */
+ CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+
+ /* Disable the IRDA Error Interrupt: (Frame error, noise error, overrun error) */
+ CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
+
+ /* Rx process is completed, restore hirda->RxState to Ready */
+ hirda->RxState = HAL_IRDA_STATE_READY;
+
+#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx complete callback */
+ hirda->RxCpltCallback(hirda);
+#else
+ /* Call legacy weak Rx complete callback */
+ HAL_IRDA_RxCpltCallback(hirda);
+#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_IRDA_SEND_REQ(hirda, IRDA_RXDATA_FLUSH_REQUEST);
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_IRDA_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_iwdg.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_iwdg.c
new file mode 100644
index 0000000000..9947bf6a87
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_iwdg.c
@@ -0,0 +1,265 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_iwdg.c
+ * @author MCD Application Team
+ * @brief IWDG HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Independent Watchdog (IWDG) peripheral:
+ * + Initialization and Start functions
+ * + IO operation functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### IWDG Generic features #####
+ ==============================================================================
+ [..]
+ (+) The IWDG can be started by either software or hardware (configurable
+ through option byte).
+
+ (+) The IWDG is clocked by Low-Speed clock (LSI) and thus stays active even
+ if the main clock fails.
+
+ (+) Once the IWDG is started, the LSI is forced ON and both can not be
+ disabled. The counter starts counting down from the reset value (0xFFF).
+ When it reaches the end of count value (0x000) a reset signal is
+ generated (IWDG reset).
+
+ (+) Whenever the key value 0x0000 AAAA is written in the IWDG_KR register,
+ the IWDG_RLR value is reloaded in the counter and the watchdog reset is
+ prevented.
+
+ (+) The IWDG is implemented in the VDD voltage domain that is still functional
+ in STOP and STANDBY mode (IWDG reset can wake-up from STANDBY).
+ IWDGRST flag in RCC_CSR register can be used to inform when an IWDG
+ reset occurs.
+
+ (+) Debug mode : When the microcontroller enters debug mode (core halted),
+ the IWDG counter either continues to work normally or stops, depending
+ on DBG_IWDG_STOP configuration bit in DBG module, accessible through
+ __HAL_DBGMCU_FREEZE_IWDG1() or __HAL_DBGMCU_FREEZE2_IWDG2() and
+ __HAL_DBGMCU_UnFreeze_IWDG1 or __HAL_DBGMCU_UnFreeze2_IWDG2() macros.
+
+ [..] Min-max timeout value @32KHz (LSI): ~125us / ~32.7s
+ The IWDG timeout may vary due to LSI frequency dispersion. STM32H7xx
+ devices provide the capability to measure the LSI frequency (LSI clock
+ connected internally to TIM16 CH1 input capture). The measured value
+ can be used to have an IWDG timeout with an acceptable accuracy.
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Use IWDG using HAL_IWDG_Init() function to :
+ (++) Enable instance by writing Start keyword in IWDG_KEY register. LSI
+ clock is forced ON and IWDG counter starts counting down.
+ (++) Enable write access to configuration registers:
+ IWDG_PR, IWDG_RLR and IWDG_WINR.
+ (++) Configure the IWDG prescaler and counter reload value. This reload
+ value will be loaded in the IWDG counter each time the watchdog is
+ reloaded, then the IWDG will start counting down from this value.
+ (++) Wait for status flags to be reset.
+ (++) Depending on window parameter:
+ (+++) If Window Init parameter is same as Window register value,
+ nothing more is done but reload counter value in order to exit
+ function with exact time base.
+ (+++) Else modify Window register. This will automatically reload
+ watchdog counter.
+
+ (#) Then the application program must refresh the IWDG counter at regular
+ intervals during normal operation to prevent an MCU reset, using
+ HAL_IWDG_Refresh() function.
+
+ *** IWDG HAL driver macros list ***
+ ====================================
+ [..]
+ Below the list of most used macros in IWDG HAL driver:
+ (+) __HAL_IWDG_START: Enable the IWDG peripheral
+ (+) __HAL_IWDG_RELOAD_COUNTER: Reloads IWDG counter with value defined in
+ the reload register
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+/** @addtogroup IWDG
+ * @brief IWDG HAL module driver.
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup IWDG_Private_Defines IWDG Private Defines
+ * @{
+ */
+/* Status register need 5 RC LSI divided by prescaler clock to be updated. With
+ higher prescaler (256), and according to LSI variation, we need to wait at
+ least 6 cycles so 48 ms. */
+#define HAL_IWDG_DEFAULT_TIMEOUT 48u
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup IWDG_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup IWDG_Exported_Functions_Group1
+ * @brief Initialization and Start functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and Start functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the IWDG according to the specified parameters in the
+ IWDG_InitTypeDef of associated handle.
+ (+) Manage Window option.
+ (+) Once initialization is performed in HAL_IWDG_Init function, Watchdog
+ is reloaded in order to exit function with correct time base.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the IWDG according to the specified parameters in the
+ * IWDG_InitTypeDef and start watchdog. Before exiting function,
+ * watchdog is refreshed in order to have correct time base.
+ * @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
+ * the configuration information for the specified IWDG module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)
+{
+ uint32_t tickstart;
+
+ /* Check the IWDG handle allocation */
+ if (hiwdg == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_IWDG_ALL_INSTANCE(hiwdg->Instance));
+ assert_param(IS_IWDG_PRESCALER(hiwdg->Init.Prescaler));
+ assert_param(IS_IWDG_RELOAD(hiwdg->Init.Reload));
+ assert_param(IS_IWDG_WINDOW(hiwdg->Init.Window));
+
+ /* Enable IWDG. LSI is turned on automatically */
+ __HAL_IWDG_START(hiwdg);
+
+ /* Enable write access to IWDG_PR, IWDG_RLR and IWDG_WINR registers by writing
+ 0x5555 in KR */
+ IWDG_ENABLE_WRITE_ACCESS(hiwdg);
+
+ /* Write to IWDG registers the Prescaler & Reload values to work with */
+ hiwdg->Instance->PR = hiwdg->Init.Prescaler;
+ hiwdg->Instance->RLR = hiwdg->Init.Reload;
+
+ /* Check pending flag, if previous update not done, return timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait for register to be updated */
+ while (hiwdg->Instance->SR != 0x00u)
+ {
+ if ((HAL_GetTick() - tickstart) > HAL_IWDG_DEFAULT_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* If window parameter is different than current value, modify window
+ register */
+ if (hiwdg->Instance->WINR != hiwdg->Init.Window)
+ {
+ /* Write to IWDG WINR the IWDG_Window value to compare with. In any case,
+ even if window feature is disabled, Watchdog will be reloaded by writing
+ windows register */
+ hiwdg->Instance->WINR = hiwdg->Init.Window;
+ }
+ else
+ {
+ /* Reload IWDG counter with value defined in the reload register */
+ __HAL_IWDG_RELOAD_COUNTER(hiwdg);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup IWDG_Exported_Functions_Group2
+ * @brief IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Refresh the IWDG.
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Refresh the IWDG.
+ * @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
+ * the configuration information for the specified IWDG module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
+{
+ /* Reload IWDG counter with value defined in the reload register */
+ __HAL_IWDG_RELOAD_COUNTER(hiwdg);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_IWDG_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_jpeg.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_jpeg.c
new file mode 100644
index 0000000000..80b34314a1
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_jpeg.c
@@ -0,0 +1,4199 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_jpeg.c
+ * @author MCD Application Team
+ * @brief JPEG HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the JPEG encoder/decoder peripheral:
+ * + Initialization and de-initialization functions
+ * + JPEG processing functions encoding and decoding
+ * + JPEG decoding Getting Info and encoding configuration setting
+ * + JPEG enable/disable header parsing functions (for decoding)
+ * + JPEG Input/Output Buffer configuration.
+ * + JPEG callback functions
+ * + JPEG Abort/Pause/Resume functions
+ * + JPEG custom quantization tables setting functions
+ * + IRQ handler management
+ * + Peripheral State and Error functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Initialize the JPEG peripheral using HAL_JPEG_Init : No initialization parameters are required.
+ Only the call to HAL_JPEG_Init is necessary to initialize the JPEG peripheral.
+
+ (#) If operation is JPEG encoding use function HAL_JPEG_ConfigEncoding to set
+ the encoding parameters (mandatory before calling the encoding function).
+ the application can change the encoding parameter ImageQuality from
+ 1 to 100 to obtain a more or less quality (visual quality vs the original row image),
+ and inversely more or less jpg file size.
+
+ (#) Note that for decoding operation the JPEG peripheral output data are organized in
+ YCbCr blocks called MCU (Minimum Coded Unit) as defioned in the JPEG specification
+ ISO/IEC 10918-1 standard.
+ It is up to the application to transform these YCbCr blocks to RGB data that can be display.
+
+ Respectively, for Encoding operation the JPEG peripheral input should be organized
+ in YCbCr MCU blocks. It is up to the application to perform the necessary RGB to YCbCr
+ MCU blocks transformation before feeding the JPEG peripheral with data.
+
+ (#) Use functions HAL_JPEG_Encode and HAL_JPEG_Decode to start respectively
+ a JPEG encoding/decoding operation in polling method (blocking).
+
+ (#) Use functions HAL_JPEG_Encode_IT and HAL_JPEG_Decode_IT to start respectively
+ a JPEG encoding/decoding operation with Interrupt method (not blocking).
+
+ (#) Use functions HAL_JPEG_Encode_DMA and HAL_JPEG_Decode_DMA to start respectively
+ a JPEG encoding/decoding operation with DMA method (not blocking).
+
+ (#) Callback HAL_JPEG_InfoReadyCallback is asserted if the current operation
+ is a JPEG decoding to provide the application with JPEG image parameters.
+ This callback is asserted when the JPEG peripheral successfully parse the
+ JPEG header.
+
+ (#) Callback HAL_JPEG_GetDataCallback is asserted for both encoding and decoding
+ operations to inform the application that the input buffer has been
+ consumed by the peripheral and to ask for a new data chunk if the operation
+ (encoding/decoding) has not been complete yet.
+
+ (++) This CallBack should be implemented in the application side. It should
+ call the function HAL_JPEG_ConfigInputBuffer if new input data are available,
+ or call HAL_JPEG_Pause with parameter XferSelection set to JPEG_PAUSE_RESUME_INPUT
+ to inform the JPEG HAL driver that the ongoing operation shall pause waiting for the
+ application to provide a new input data chunk.
+ Once the application succeed getting new data and if the input has been paused,
+ the application can call the function HAL_JPEG_ConfigInputBuffer to set the new
+ input buffer and size, then resume the JPEG HAL input by calling new function HAL_JPEG_Resume.
+ If the application has ended feeding the HAL JPEG with input data (no more input data), the application
+ Should call the function HAL_JPEG_ConfigInputBuffer (within the callback HAL_JPEG_GetDataCallback)
+ with the parameter InDataLength set to zero.
+
+ (++) The mechanism of HAL_JPEG_ConfigInputBuffer/HAL_JPEG_Pause/HAL_JPEG_Resume allows
+ to the application to provide the input data (for encoding or decoding) by chunks.
+ If the new input data chunk is not available (because data should be read from an input file
+ for example) the application can pause the JPEG input (using function HAL_JPEG_Pause)
+ Once the new input data chunk is available ( read from a file for example), the application
+ can call the function HAL_JPEG_ConfigInputBuffer to provide the HAL with the new chunk
+ then resume the JPEG HAL input by calling function HAL_JPEG_Resume.
+
+ (++) The application can call functions HAL_JPEG_ConfigInputBuffer then HAL_JPEG_Resume.
+ any time (outside the HAL_JPEG_GetDataCallback) Once the new input chunk data available.
+ However, to keep data coherency, the function HAL_JPEG_Pause must be imperatively called
+ (if necessary) within the callback HAL_JPEG_GetDataCallback, i.e when the HAL JPEG has ended
+ Transferring the previous chunk buffer to the JPEG peripheral.
+
+ (#) Callback HAL_JPEG_DataReadyCallback is asserted when the HAL JPEG driver
+ has filled the given output buffer with the given size.
+
+ (++) This CallBack should be implemented in the application side. It should
+ call the function HAL_JPEG_ConfigOutputBuffer to provide the HAL JPEG driver
+ with the new output buffer location and size to be used to store next data chunk.
+ if the application is not ready to provide the output chunk location then it can
+ call the function HAL_JPEG_Pause with parameter XferSelection set to JPEG_PAUSE_RESUME_OUTPUT
+ to inform the JPEG HAL driver that it shall pause output data. Once the application
+ is ready to receive the new data chunk (output buffer location free or available) it should call
+ the function HAL_JPEG_ConfigOutputBuffer to provide the HAL JPEG driver
+ with the new output chunk buffer location and size, then call HAL_JPEG_Resume
+ to inform the HAL that it shall resume outputting data in the given output buffer.
+
+ (++) The mechanism of HAL_JPEG_ConfigOutputBuffer/HAL_JPEG_Pause/HAL_JPEG_Resume allows
+ the application to receive data from the JPEG peripheral by chunks. when a chunk
+ is received, the application can pause the HAL JPEG output data to be able to process
+ these received data (YCbCr to RGB conversion in case of decoding or data storage in case
+ of encoding).
+
+ (++) The application can call functions HAL_JPEG_ ConfigOutputBuffer then HAL_JPEG_Resume.
+ any time (outside the HAL_JPEG_DataReadyCallback) Once the output data buffer is free to use.
+ However, to keep data coherency, the function HAL_JPEG_Pause must be imperatively called
+ (if necessary) within the callback HAL_JPEG_ DataReadyCallback, i.e when the HAL JPEG has ended
+ Transferring the previous chunk buffer from the JPEG peripheral to the application.
+
+ (#) Callback HAL_JPEG_EncodeCpltCallback is asserted when the HAL JPEG driver has
+ ended the current JPEG encoding operation, and all output data has been transmitted
+ to the application.
+
+ (#) Callback HAL_JPEG_DecodeCpltCallback is asserted when the HAL JPEG driver has
+ ended the current JPEG decoding operation. and all output data has been transmitted
+ to the application.
+
+ (#) Callback HAL_JPEG_ErrorCallback is asserted when an error occurred during
+ the current operation. the application can call the function HAL_JPEG_GetError()
+ to retrieve the error codes.
+
+ (#) By default the HAL JPEG driver uses the default quantization tables
+ as provide in the JPEG specification (ISO/IEC 10918-1 standard) for encoding.
+ User can change these default tables if necessary using the function HAL_JPEG_SetUserQuantTables
+ Note that for decoding the quantization tables are automatically extracted from
+ the JPEG header.
+
+ (#) To control JPEG state you can use the following function: HAL_JPEG_GetState()
+
+ *** JPEG HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in JPEG HAL driver.
+
+ (+) __HAL_JPEG_RESET_HANDLE_STATE : Reset JPEG handle state.
+ (+) __HAL_JPEG_ENABLE : Enable the JPEG peripheral.
+ (+) __HAL_JPEG_DISABLE : Disable the JPEG peripheral.
+ (+) __HAL_JPEG_GET_FLAG : Check the specified JPEG status flag.
+ (+) __HAL_JPEG_CLEAR_FLAG : Clear the specified JPEG status flag.
+ (+) __HAL_JPEG_ENABLE_IT : Enable the specified JPEG Interrupt.
+ (+) __HAL_JPEG_DISABLE_IT : Disable the specified JPEG Interrupt.
+ (+) __HAL_JPEG_GET_IT_SOURCE : returns the state of the specified JPEG Interrupt (Enabled or disabled).
+
+ *** Callback registration ***
+ =============================================
+
+ The compilation define USE_HAL_JPEG_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions HAL_JPEG_RegisterCallback() or HAL_JPEG_RegisterXXXCallback()
+ to register an interrupt callback.
+
+ Function HAL_JPEG_RegisterCallback() allows to register following callbacks:
+ (+) EncodeCpltCallback : callback for end of encoding operation.
+ (+) DecodeCpltCallback : callback for end of decoding operation.
+ (+) ErrorCallback : callback for error detection.
+ (+) MspInitCallback : JPEG MspInit.
+ (+) MspDeInitCallback : JPEG MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ For specific callbacks InfoReadyCallback, GetDataCallback and DataReadyCallback use dedicated
+ register callbacks : respectively HAL_JPEG_RegisterInfoReadyCallback(),
+ HAL_JPEG_RegisterGetDataCallback() and HAL_JPEG_RegisterDataReadyCallback().
+
+ Use function HAL_JPEG_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ HAL_JPEG_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) EncodeCpltCallback : callback for end of encoding operation.
+ (+) DecodeCpltCallback : callback for end of decoding operation.
+ (+) ErrorCallback : callback for error detection.
+ (+) MspInitCallback : JPEG MspInit.
+ (+) MspDeInitCallback : JPEG MspDeInit.
+
+ For callbacks InfoReadyCallback, GetDataCallback and DataReadyCallback use dedicated
+ unregister callbacks : respectively HAL_JPEG_UnRegisterInfoReadyCallback(),
+ HAL_JPEG_UnRegisterGetDataCallback() and HAL_JPEG_UnRegisterDataReadyCallback().
+
+ By default, after the HAL_JPEG_Init() and when the state is HAL_JPEG_STATE_RESET
+ all callbacks are set to the corresponding weak functions :
+ examples HAL_JPEG_DecodeCpltCallback() , HAL_JPEG_GetDataCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak function in the HAL_JPEG_Init()/ HAL_JPEG_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ if not, MspInit or MspDeInit are not null, the HAL_JPEG_Init() / HAL_JPEG_DeInit()
+ keep and use the user MspInit/MspDeInit functions (registered beforehand)
+
+ Callbacks can be registered/unregistered in HAL_JPEG_STATE_READY state only.
+ Exception done MspInit/MspDeInit callbacks that can be registered/unregistered
+ in HAL_JPEG_STATE_READY or HAL_JPEG_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_JPEG_RegisterCallback() before calling HAL_JPEG_DeInit()
+ or HAL_JPEG_Init() function.
+
+ When The compilation define USE_HAL_JPEG_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup JPEG JPEG
+ * @brief JPEG HAL module driver.
+ * @{
+ */
+
+#ifdef HAL_JPEG_MODULE_ENABLED
+
+#if defined (JPEG)
+
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup JPEG_Private_Constants
+ * @{
+ */
+#define JPEG_TIMEOUT_VALUE ((uint32_t)1000) /* 1s */
+#define JPEG_AC_HUFF_TABLE_SIZE ((uint32_t)162) /* Huffman AC table size : 162 codes*/
+#define JPEG_DC_HUFF_TABLE_SIZE ((uint32_t)12) /* Huffman AC table size : 12 codes*/
+
+#define JPEG_FIFO_SIZE ((uint32_t)16U) /* JPEG Input/Output HW FIFO size in words*/
+
+#define JPEG_FIFO_TH_SIZE ((uint32_t)8U) /* JPEG Input/Output HW FIFO Threshold in words*/
+
+#define JPEG_INTERRUPT_MASK ((uint32_t)0x0000007EU) /* JPEG Interrupt Mask*/
+
+#define JPEG_CONTEXT_ENCODE ((uint32_t)0x00000001) /* JPEG context : operation is encoding*/
+#define JPEG_CONTEXT_DECODE ((uint32_t)0x00000002) /* JPEG context : operation is decoding*/
+#define JPEG_CONTEXT_OPERATION_MASK ((uint32_t)0x00000003) /* JPEG context : operation Mask */
+
+#define JPEG_CONTEXT_POLLING ((uint32_t)0x00000004) /* JPEG context : Transfer use Polling */
+#define JPEG_CONTEXT_IT ((uint32_t)0x00000008) /* JPEG context : Transfer use Interrupt */
+#define JPEG_CONTEXT_DMA ((uint32_t)0x0000000C) /* JPEG context : Transfer use DMA */
+#define JPEG_CONTEXT_METHOD_MASK ((uint32_t)0x0000000C) /* JPEG context : Transfer Mask */
+
+
+#define JPEG_CONTEXT_CONF_ENCODING ((uint32_t)0x00000100) /* JPEG context : encoding config done */
+
+#define JPEG_CONTEXT_PAUSE_INPUT ((uint32_t)0x00001000) /* JPEG context : Pause Input */
+#define JPEG_CONTEXT_PAUSE_OUTPUT ((uint32_t)0x00002000) /* JPEG context : Pause Output */
+
+#define JPEG_CONTEXT_CUSTOM_TABLES ((uint32_t)0x00004000) /* JPEG context : Use custom quantization tables */
+
+#define JPEG_CONTEXT_ENDING_DMA ((uint32_t)0x00008000) /* JPEG context : ending with DMA in progress */
+
+#define JPEG_PROCESS_ONGOING ((uint32_t)0x00000000) /* Process is on going */
+#define JPEG_PROCESS_DONE ((uint32_t)0x00000001) /* Process is done (ends) */
+/**
+ * @}
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/** @addtogroup JPEG_Private_Types
+ * @{
+ */
+
+/*
+ JPEG Huffman Table Structure definition :
+ This implementation of Huffman table structure is compliant with ISO/IEC 10918-1 standard , Annex C Huffman Table specification
+ */
+typedef struct
+{
+ /* These two fields directly represent the contents of a JPEG DHT marker */
+ uint8_t Bits[16]; /*!< bits[k] = # of symbols with codes of length k bits, this parameter corresponds to BITS list in the Annex C */
+
+ uint8_t HuffVal[162]; /*!< The symbols, in order of incremented code length, this parameter corresponds to HUFFVAL list in the Annex C */
+
+
+} JPEG_ACHuffTableTypeDef;
+
+typedef struct
+{
+ /* These two fields directly represent the contents of a JPEG DHT marker */
+ uint8_t Bits[16]; /*!< bits[k] = # of symbols with codes of length k bits, this parameter corresponds to BITS list in the Annex C */
+
+ uint8_t HuffVal[12]; /*!< The symbols, in order of incremented code length, this parameter corresponds to HUFFVAL list in the Annex C */
+
+
+} JPEG_DCHuffTableTypeDef;
+
+typedef struct
+{
+ uint8_t CodeLength[JPEG_AC_HUFF_TABLE_SIZE]; /*!< Code length */
+
+ uint32_t HuffmanCode[JPEG_AC_HUFF_TABLE_SIZE]; /*!< HuffmanCode */
+
+} JPEG_AC_HuffCodeTableTypeDef;
+
+typedef struct
+{
+ uint8_t CodeLength[JPEG_DC_HUFF_TABLE_SIZE]; /*!< Code length */
+
+ uint32_t HuffmanCode[JPEG_DC_HUFF_TABLE_SIZE]; /*!< HuffmanCode */
+
+} JPEG_DC_HuffCodeTableTypeDef;
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+
+/* Private variables ---------------------------------------------------------*/
+/** @addtogroup JPEG_Private_Variables
+ * @{
+ */
+
+static const JPEG_DCHuffTableTypeDef JPEG_DCLUM_HuffTable =
+{
+ { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, /*Bits*/
+
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb } /*HUFFVAL */
+
+};
+
+static const JPEG_DCHuffTableTypeDef JPEG_DCCHROM_HuffTable =
+{
+ { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, /*Bits*/
+
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb } /*HUFFVAL */
+};
+
+static const JPEG_ACHuffTableTypeDef JPEG_ACLUM_HuffTable =
+{
+ { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }, /*Bits*/
+
+ {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, /*HUFFVAL */
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+ }
+};
+
+static const JPEG_ACHuffTableTypeDef JPEG_ACCHROM_HuffTable =
+{
+ { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }, /*Bits*/
+
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, /*HUFFVAL */
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+ }
+};
+
+static const uint8_t JPEG_ZIGZAG_ORDER[JPEG_QUANT_TABLE_SIZE] =
+{
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+};
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup JPEG_Private_Functions_Prototypes
+ * @{
+ */
+
+static HAL_StatusTypeDef JPEG_Bits_To_SizeCodes(uint8_t *Bits, uint8_t *Huffsize, uint32_t *Huffcode, uint32_t *LastK);
+static HAL_StatusTypeDef JPEG_DCHuff_BitsVals_To_SizeCodes(JPEG_DCHuffTableTypeDef *DC_BitsValsTable,
+ JPEG_DC_HuffCodeTableTypeDef *DC_SizeCodesTable);
+static HAL_StatusTypeDef JPEG_ACHuff_BitsVals_To_SizeCodes(JPEG_ACHuffTableTypeDef *AC_BitsValsTable,
+ JPEG_AC_HuffCodeTableTypeDef *AC_SizeCodesTable);
+static HAL_StatusTypeDef JPEG_Set_HuffDC_Mem(JPEG_HandleTypeDef *hjpeg, JPEG_DCHuffTableTypeDef *HuffTableDC,
+ const __IO uint32_t *DCTableAddress);
+static HAL_StatusTypeDef JPEG_Set_HuffAC_Mem(JPEG_HandleTypeDef *hjpeg, JPEG_ACHuffTableTypeDef *HuffTableAC,
+ const __IO uint32_t *ACTableAddress);
+static HAL_StatusTypeDef JPEG_Set_HuffEnc_Mem(JPEG_HandleTypeDef *hjpeg);
+static void JPEG_Set_Huff_DHTMem(JPEG_HandleTypeDef *hjpeg);
+static uint32_t JPEG_Set_Quantization_Mem(JPEG_HandleTypeDef *hjpeg, uint8_t *QTable,
+ __IO uint32_t *QTableAddress);
+static void JPEG_SetColorYCBCR(JPEG_HandleTypeDef *hjpeg);
+static void JPEG_SetColorGrayScale(JPEG_HandleTypeDef *hjpeg);
+static void JPEG_SetColorCMYK(JPEG_HandleTypeDef *hjpeg);
+
+static void JPEG_Init_Process(JPEG_HandleTypeDef *hjpeg);
+static uint32_t JPEG_Process(JPEG_HandleTypeDef *hjpeg);
+static void JPEG_ReadInputData(JPEG_HandleTypeDef *hjpeg, uint32_t nbRequestWords);
+static void JPEG_StoreOutputData(JPEG_HandleTypeDef *hjpeg, uint32_t nbOutputWords);
+static uint32_t JPEG_GetQuality(JPEG_HandleTypeDef *hjpeg);
+
+static HAL_StatusTypeDef JPEG_DMA_StartProcess(JPEG_HandleTypeDef *hjpeg);
+static void JPEG_DMA_ContinueProcess(JPEG_HandleTypeDef *hjpeg);
+static void JPEG_DMA_EndProcess(JPEG_HandleTypeDef *hjpeg);
+static void JPEG_DMA_PollResidualData(JPEG_HandleTypeDef *hjpeg);
+static void JPEG_MDMAOutCpltCallback(MDMA_HandleTypeDef *hmdma);
+static void JPEG_MDMAInCpltCallback(MDMA_HandleTypeDef *hmdma);
+static void JPEG_MDMAErrorCallback(MDMA_HandleTypeDef *hmdma);
+static void JPEG_MDMAOutAbortCallback(MDMA_HandleTypeDef *hmdma);
+
+/**
+ * @}
+ */
+
+/** @defgroup JPEG_Exported_Functions JPEG Exported Functions
+ * @{
+ */
+
+/** @defgroup JPEG_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and de-initialization functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the JPEG peripheral and creates the associated handle
+ (+) DeInitialize the JPEG peripheral
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the JPEG according to the specified
+ * parameters in the JPEG_InitTypeDef and creates the associated handle.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Init(JPEG_HandleTypeDef *hjpeg)
+{
+ /* These are the sample quantization tables given in JPEG spec ISO/IEC 10918-1 standard , section K.1. */
+ static const uint8_t JPEG_LUM_QuantTable[JPEG_QUANT_TABLE_SIZE] =
+ {
+ 16, 11, 10, 16, 24, 40, 51, 61,
+ 12, 12, 14, 19, 26, 58, 60, 55,
+ 14, 13, 16, 24, 40, 57, 69, 56,
+ 14, 17, 22, 29, 51, 87, 80, 62,
+ 18, 22, 37, 56, 68, 109, 103, 77,
+ 24, 35, 55, 64, 81, 104, 113, 92,
+ 49, 64, 78, 87, 103, 121, 120, 101,
+ 72, 92, 95, 98, 112, 100, 103, 99
+ };
+ static const uint8_t JPEG_CHROM_QuantTable[JPEG_QUANT_TABLE_SIZE] =
+ {
+ 17, 18, 24, 47, 99, 99, 99, 99,
+ 18, 21, 26, 66, 99, 99, 99, 99,
+ 24, 26, 56, 99, 99, 99, 99, 99,
+ 47, 66, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99
+ };
+
+ /* Check the JPEG handle allocation */
+ if (hjpeg == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ if (hjpeg->State == HAL_JPEG_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hjpeg->Lock = HAL_UNLOCKED;
+
+ hjpeg->InfoReadyCallback = HAL_JPEG_InfoReadyCallback; /* Legacy weak InfoReadyCallback */
+ hjpeg->EncodeCpltCallback = HAL_JPEG_EncodeCpltCallback; /* Legacy weak EncodeCpltCallback */
+ hjpeg->DecodeCpltCallback = HAL_JPEG_DecodeCpltCallback; /* Legacy weak DecodeCpltCallback */
+ hjpeg->ErrorCallback = HAL_JPEG_ErrorCallback; /* Legacy weak ErrorCallback */
+ hjpeg->GetDataCallback = HAL_JPEG_GetDataCallback; /* Legacy weak GetDataCallback */
+ hjpeg->DataReadyCallback = HAL_JPEG_DataReadyCallback; /* Legacy weak DataReadyCallback */
+
+ if (hjpeg->MspInitCallback == NULL)
+ {
+ hjpeg->MspInitCallback = HAL_JPEG_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware */
+ hjpeg->MspInitCallback(hjpeg);
+ }
+#else
+ if (hjpeg->State == HAL_JPEG_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hjpeg->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_JPEG_MspInit(hjpeg);
+ }
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_BUSY;
+
+ /* Start the JPEG Core*/
+ __HAL_JPEG_ENABLE(hjpeg);
+
+ /* Stop the JPEG encoding/decoding process*/
+ hjpeg->Instance->CONFR0 &= ~JPEG_CONFR0_START;
+
+ /* Disable All Interrupts */
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_INTERRUPT_MASK);
+
+
+ /* Flush input and output FIFOs*/
+ hjpeg->Instance->CR |= JPEG_CR_IFF;
+ hjpeg->Instance->CR |= JPEG_CR_OFF;
+
+ /* Clear all flags */
+ __HAL_JPEG_CLEAR_FLAG(hjpeg, JPEG_FLAG_ALL);
+
+ /* init default quantization tables*/
+ hjpeg->QuantTable0 = (uint8_t *)((uint32_t)JPEG_LUM_QuantTable);
+ hjpeg->QuantTable1 = (uint8_t *)((uint32_t)JPEG_CHROM_QuantTable);
+ hjpeg->QuantTable2 = NULL;
+ hjpeg->QuantTable3 = NULL;
+
+ /* init the default Huffman tables*/
+ if (JPEG_Set_HuffEnc_Mem(hjpeg) != HAL_OK)
+ {
+ hjpeg->ErrorCode = HAL_JPEG_ERROR_HUFF_TABLE;
+
+ return HAL_ERROR;
+ }
+
+ /* Enable header processing*/
+ hjpeg->Instance->CONFR1 |= JPEG_CONFR1_HDR;
+
+ /* Reset JpegInCount and JpegOutCount */
+ hjpeg->JpegInCount = 0;
+ hjpeg->JpegOutCount = 0;
+
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ /* Reset the JPEG ErrorCode */
+ hjpeg->ErrorCode = HAL_JPEG_ERROR_NONE;
+
+ /*Clear the context filelds*/
+ hjpeg->Context = 0;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the JPEG peripheral.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_DeInit(JPEG_HandleTypeDef *hjpeg)
+{
+ /* Check the JPEG handle allocation */
+ if (hjpeg == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ if (hjpeg->MspDeInitCallback == NULL)
+ {
+ hjpeg->MspDeInitCallback = HAL_JPEG_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware */
+ hjpeg->MspDeInitCallback(hjpeg);
+
+#else
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ HAL_JPEG_MspDeInit(hjpeg);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_BUSY;
+
+ /* Reset the JPEG ErrorCode */
+ hjpeg->ErrorCode = HAL_JPEG_ERROR_NONE;
+
+ /* Reset JpegInCount and JpegOutCount */
+ hjpeg->JpegInCount = 0;
+ hjpeg->JpegOutCount = 0;
+
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_RESET;
+
+ /*Clear the context fields*/
+ hjpeg->Context = 0;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the JPEG MSP.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+__weak void HAL_JPEG_MspInit(JPEG_HandleTypeDef *hjpeg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hjpeg);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_JPEG_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes JPEG MSP.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+__weak void HAL_JPEG_MspDeInit(JPEG_HandleTypeDef *hjpeg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hjpeg);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_JPEG_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User JPEG Callback
+ * To be used instead of the weak predefined callback
+ * @param hjpeg JPEG handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_JPEG_ENCODE_CPLT_CB_ID Encode Complete callback ID
+ * @arg @ref HAL_JPEG_DECODE_CPLT_CB_ID Decode Complete callback ID
+ * @arg @ref HAL_JPEG_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_JPEG_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_JPEG_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_RegisterCallback(JPEG_HandleTypeDef *hjpeg, HAL_JPEG_CallbackIDTypeDef CallbackID,
+ pJPEG_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (HAL_JPEG_STATE_READY == hjpeg->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_JPEG_ENCODE_CPLT_CB_ID :
+ hjpeg->EncodeCpltCallback = pCallback;
+ break;
+
+ case HAL_JPEG_DECODE_CPLT_CB_ID :
+ hjpeg->DecodeCpltCallback = pCallback;
+ break;
+
+ case HAL_JPEG_ERROR_CB_ID :
+ hjpeg->ErrorCallback = pCallback;
+ break;
+
+ case HAL_JPEG_MSPINIT_CB_ID :
+ hjpeg->MspInitCallback = pCallback;
+ break;
+
+ case HAL_JPEG_MSPDEINIT_CB_ID :
+ hjpeg->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_JPEG_STATE_RESET == hjpeg->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_JPEG_MSPINIT_CB_ID :
+ hjpeg->MspInitCallback = pCallback;
+ break;
+
+ case HAL_JPEG_MSPDEINIT_CB_ID :
+ hjpeg->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hjpeg);
+ return status;
+}
+
+/**
+ * @brief Unregister a JPEG Callback
+ * JPEG callabck is redirected to the weak predefined callback
+ * @param hjpeg JPEG handle
+ * @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_JPEG_ENCODE_CPLT_CB_ID Encode Complete callback ID
+ * @arg @ref HAL_JPEG_DECODE_CPLT_CB_ID Decode Complete callback ID
+ * @arg @ref HAL_JPEG_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_JPEG_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_JPEG_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_UnRegisterCallback(JPEG_HandleTypeDef *hjpeg, HAL_JPEG_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (HAL_JPEG_STATE_READY == hjpeg->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_JPEG_ENCODE_CPLT_CB_ID :
+ hjpeg->EncodeCpltCallback = HAL_JPEG_EncodeCpltCallback; /* Legacy weak EncodeCpltCallback */
+ break;
+
+ case HAL_JPEG_DECODE_CPLT_CB_ID :
+ hjpeg->DecodeCpltCallback = HAL_JPEG_DecodeCpltCallback; /* Legacy weak DecodeCpltCallback */
+ break;
+
+ case HAL_JPEG_ERROR_CB_ID :
+ hjpeg->ErrorCallback = HAL_JPEG_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_JPEG_MSPINIT_CB_ID :
+ hjpeg->MspInitCallback = HAL_JPEG_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_JPEG_MSPDEINIT_CB_ID :
+ hjpeg->MspDeInitCallback = HAL_JPEG_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_JPEG_STATE_RESET == hjpeg->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_JPEG_MSPINIT_CB_ID :
+ hjpeg->MspInitCallback = HAL_JPEG_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_JPEG_MSPDEINIT_CB_ID :
+ hjpeg->MspDeInitCallback = HAL_JPEG_MspDeInit; /* Legacy weak MspInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hjpeg);
+ return status;
+}
+
+/**
+ * @brief Register Info Ready JPEG Callback
+ * To be used instead of the weak HAL_JPEG_InfoReadyCallback() predefined callback
+ * @param hjpeg JPEG handle
+ * @param pCallback pointer to the Info Ready Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_RegisterInfoReadyCallback(JPEG_HandleTypeDef *hjpeg,
+ pJPEG_InfoReadyCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (HAL_JPEG_STATE_READY == hjpeg->State)
+ {
+ hjpeg->InfoReadyCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hjpeg);
+ return status;
+}
+
+/**
+ * @brief UnRegister the Info Ready JPEG Callback
+ * Info Ready JPEG Callback is redirected to the weak HAL_JPEG_InfoReadyCallback() predefined callback
+ * @param hjpeg JPEG handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_UnRegisterInfoReadyCallback(JPEG_HandleTypeDef *hjpeg)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (HAL_JPEG_STATE_READY == hjpeg->State)
+ {
+ hjpeg->InfoReadyCallback = HAL_JPEG_InfoReadyCallback; /* Legacy weak InfoReadyCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hjpeg);
+ return status;
+}
+
+/**
+ * @brief Register Get Data JPEG Callback
+ * To be used instead of the weak HAL_JPEG_GetDataCallback() predefined callback
+ * @param hjpeg JPEG handle
+ * @param pCallback pointer to the Get Data Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_RegisterGetDataCallback(JPEG_HandleTypeDef *hjpeg, pJPEG_GetDataCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (HAL_JPEG_STATE_READY == hjpeg->State)
+ {
+ hjpeg->GetDataCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hjpeg);
+ return status;
+}
+
+/**
+ * @brief UnRegister the Get Data JPEG Callback
+ * Get Data JPEG Callback is redirected to the weak HAL_JPEG_GetDataCallback() predefined callback
+ * @param hjpeg JPEG handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_UnRegisterGetDataCallback(JPEG_HandleTypeDef *hjpeg)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (HAL_JPEG_STATE_READY == hjpeg->State)
+ {
+ hjpeg->GetDataCallback = HAL_JPEG_GetDataCallback; /* Legacy weak GetDataCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hjpeg);
+ return status;
+}
+
+/**
+ * @brief Register Data Ready JPEG Callback
+ * To be used instead of the weak HAL_JPEG_DataReadyCallback() predefined callback
+ * @param hjpeg JPEG handle
+ * @param pCallback pointer to the Get Data Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_RegisterDataReadyCallback(JPEG_HandleTypeDef *hjpeg,
+ pJPEG_DataReadyCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (HAL_JPEG_STATE_READY == hjpeg->State)
+ {
+ hjpeg->DataReadyCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hjpeg);
+ return status;
+}
+
+/**
+ * @brief UnRegister the Data Ready JPEG Callback
+ * Get Data Ready Callback is redirected to the weak HAL_JPEG_DataReadyCallback() predefined callback
+ * @param hjpeg JPEG handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_UnRegisterDataReadyCallback(JPEG_HandleTypeDef *hjpeg)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (HAL_JPEG_STATE_READY == hjpeg->State)
+ {
+ hjpeg->DataReadyCallback = HAL_JPEG_DataReadyCallback; /* Legacy weak DataReadyCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hjpeg);
+ return status;
+}
+
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup JPEG_Exported_Functions_Group2 Configuration functions
+ * @brief JPEG Configuration functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Configuration functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) HAL_JPEG_ConfigEncoding() : JPEG encoding configuration
+ (+) HAL_JPEG_GetInfo() : Extract the image configuration from the JPEG header during the decoding
+ (+) HAL_JPEG_EnableHeaderParsing() : Enable JPEG Header parsing for decoding
+ (+) HAL_JPEG_DisableHeaderParsing() : Disable JPEG Header parsing for decoding
+ (+) HAL_JPEG_SetUserQuantTables : Modify the default Quantization tables used for JPEG encoding.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set the JPEG encoding configuration.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pConf pointer to a JPEG_ConfTypeDef structure that contains
+ * the encoding configuration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_ConfigEncoding(JPEG_HandleTypeDef *hjpeg, JPEG_ConfTypeDef *pConf)
+{
+ uint32_t error;
+ uint32_t numberMCU;
+ uint32_t hfactor;
+ uint32_t vfactor;
+ uint32_t hMCU;
+ uint32_t vMCU;
+
+ /* Check the JPEG handle allocation */
+ if ((hjpeg == NULL) || (pConf == NULL))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameters */
+ assert_param(IS_JPEG_COLORSPACE(pConf->ColorSpace));
+ assert_param(IS_JPEG_CHROMASUBSAMPLING(pConf->ChromaSubsampling));
+ assert_param(IS_JPEG_IMAGE_QUALITY(pConf->ImageQuality));
+
+ /* Process Locked */
+ __HAL_LOCK(hjpeg);
+
+ if (hjpeg->State == HAL_JPEG_STATE_READY)
+ {
+ hjpeg->State = HAL_JPEG_STATE_BUSY;
+
+ hjpeg->Conf.ColorSpace = pConf->ColorSpace;
+ hjpeg->Conf.ChromaSubsampling = pConf->ChromaSubsampling;
+ hjpeg->Conf.ImageHeight = pConf->ImageHeight;
+ hjpeg->Conf.ImageWidth = pConf->ImageWidth;
+ hjpeg->Conf.ImageQuality = pConf->ImageQuality;
+
+ /* Reset the Color Space : by default only one quantization table is used*/
+ hjpeg->Instance->CONFR1 &= ~JPEG_CONFR1_COLORSPACE;
+
+ /* Set Number of color components*/
+ if (hjpeg->Conf.ColorSpace == JPEG_GRAYSCALE_COLORSPACE)
+ {
+ /*Gray Scale is only one component 8x8 blocks i.e 4:4:4*/
+ hjpeg->Conf.ChromaSubsampling = JPEG_444_SUBSAMPLING;
+
+ JPEG_SetColorGrayScale(hjpeg);
+ /* Set quantization table 0*/
+ error = JPEG_Set_Quantization_Mem(hjpeg, hjpeg->QuantTable0, (hjpeg->Instance->QMEM0));
+ }
+ else if (hjpeg->Conf.ColorSpace == JPEG_YCBCR_COLORSPACE)
+ {
+ /*
+ Set the Color Space for YCbCr : 2 quantization tables are used
+ one for Luminance(Y) and one for both Chrominances (Cb & Cr)
+ */
+ hjpeg->Instance->CONFR1 |= JPEG_CONFR1_COLORSPACE_0;
+
+ JPEG_SetColorYCBCR(hjpeg);
+
+ /* Set quantization table 0*/
+ error = JPEG_Set_Quantization_Mem(hjpeg, hjpeg->QuantTable0, (hjpeg->Instance->QMEM0));
+ /*By default quantization table 0 for component 0 and quantization table 1 for both components 1 and 2*/
+ error |= JPEG_Set_Quantization_Mem(hjpeg, hjpeg->QuantTable1, (hjpeg->Instance->QMEM1));
+
+ if ((hjpeg->Context & JPEG_CONTEXT_CUSTOM_TABLES) != 0UL)
+ {
+ /*Use user customized quantization tables , 1 table per component*/
+ /* use 3 quantization tables , one for each component*/
+ hjpeg->Instance->CONFR1 &= (~JPEG_CONFR1_COLORSPACE);
+ hjpeg->Instance->CONFR1 |= JPEG_CONFR1_COLORSPACE_1;
+
+ error |= JPEG_Set_Quantization_Mem(hjpeg, hjpeg->QuantTable2, (hjpeg->Instance->QMEM2));
+
+ /*Use Quantization 1 table for component 1*/
+ hjpeg->Instance->CONFR5 &= (~JPEG_CONFR5_QT);
+ hjpeg->Instance->CONFR5 |= JPEG_CONFR5_QT_0;
+
+ /*Use Quantization 2 table for component 2*/
+ hjpeg->Instance->CONFR6 &= (~JPEG_CONFR6_QT);
+ hjpeg->Instance->CONFR6 |= JPEG_CONFR6_QT_1;
+ }
+ }
+ else /* ColorSpace == JPEG_CMYK_COLORSPACE */
+ {
+ JPEG_SetColorCMYK(hjpeg);
+
+ /* Set quantization table 0*/
+ error = JPEG_Set_Quantization_Mem(hjpeg, hjpeg->QuantTable0, (hjpeg->Instance->QMEM0));
+ /*By default quantization table 0 for All components*/
+
+ if ((hjpeg->Context & JPEG_CONTEXT_CUSTOM_TABLES) != 0UL)
+ {
+ /*Use user customized quantization tables , 1 table per component*/
+ /* use 4 quantization tables , one for each component*/
+ hjpeg->Instance->CONFR1 |= JPEG_CONFR1_COLORSPACE;
+
+ error |= JPEG_Set_Quantization_Mem(hjpeg, hjpeg->QuantTable1, (hjpeg->Instance->QMEM1));
+ error |= JPEG_Set_Quantization_Mem(hjpeg, hjpeg->QuantTable2, (hjpeg->Instance->QMEM2));
+ error |= JPEG_Set_Quantization_Mem(hjpeg, hjpeg->QuantTable3, (hjpeg->Instance->QMEM3));
+
+ /*Use Quantization 1 table for component 1*/
+ hjpeg->Instance->CONFR5 |= JPEG_CONFR5_QT_0;
+
+ /*Use Quantization 2 table for component 2*/
+ hjpeg->Instance->CONFR6 |= JPEG_CONFR6_QT_1;
+
+ /*Use Quantization 3 table for component 3*/
+ hjpeg->Instance->CONFR7 |= JPEG_CONFR7_QT;
+ }
+ }
+
+ if (error != 0UL)
+ {
+ hjpeg->ErrorCode = HAL_JPEG_ERROR_QUANT_TABLE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Set the JPEG State to ready */
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ /* Set the image size*/
+ /* set the number of lines*/
+ MODIFY_REG(hjpeg->Instance->CONFR1, JPEG_CONFR1_YSIZE, ((hjpeg->Conf.ImageHeight & 0x0000FFFFUL) << 16));
+ /* set the number of pixels per line*/
+ MODIFY_REG(hjpeg->Instance->CONFR3, JPEG_CONFR3_XSIZE, ((hjpeg->Conf.ImageWidth & 0x0000FFFFUL) << 16));
+
+
+ if (hjpeg->Conf.ChromaSubsampling == JPEG_420_SUBSAMPLING) /* 4:2:0*/
+ {
+ hfactor = 16;
+ vfactor = 16;
+ }
+ else if (hjpeg->Conf.ChromaSubsampling == JPEG_422_SUBSAMPLING) /* 4:2:2*/
+ {
+ hfactor = 16;
+ vfactor = 8;
+ }
+ else /* Default is 8x8 MCU, 4:4:4*/
+ {
+ hfactor = 8;
+ vfactor = 8;
+ }
+
+ hMCU = (hjpeg->Conf.ImageWidth / hfactor);
+ if ((hjpeg->Conf.ImageWidth % hfactor) != 0UL)
+ {
+ hMCU++; /*+1 for horizontal incomplete MCU */
+ }
+
+ vMCU = (hjpeg->Conf.ImageHeight / vfactor);
+ if ((hjpeg->Conf.ImageHeight % vfactor) != 0UL)
+ {
+ vMCU++; /*+1 for vertical incomplete MCU */
+ }
+
+ numberMCU = (hMCU * vMCU) - 1UL; /* Bit Field JPEG_CONFR2_NMCU shall be set to NB_MCU - 1*/
+ /* Set the number of MCU*/
+ hjpeg->Instance->CONFR2 = (numberMCU & JPEG_CONFR2_NMCU);
+
+ hjpeg->Context |= JPEG_CONTEXT_CONF_ENCODING;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Set the JPEG State to ready */
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Return function status */
+ return HAL_BUSY;
+ }
+ }
+}
+
+/**
+ * @brief Extract the image configuration from the JPEG header during the decoding
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pInfo pointer to a JPEG_ConfTypeDef structure that contains
+ * The JPEG decoded header informations
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_GetInfo(JPEG_HandleTypeDef *hjpeg, JPEG_ConfTypeDef *pInfo)
+{
+ uint32_t yblockNb;
+ uint32_t cBblockNb;
+ uint32_t cRblockNb;
+
+ /* Check the JPEG handle allocation */
+ if ((hjpeg == NULL) || (pInfo == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /*Read the conf parameters */
+ if ((hjpeg->Instance->CONFR1 & JPEG_CONFR1_NF) == JPEG_CONFR1_NF_1)
+ {
+ pInfo->ColorSpace = JPEG_YCBCR_COLORSPACE;
+ }
+ else if ((hjpeg->Instance->CONFR1 & JPEG_CONFR1_NF) == 0UL)
+ {
+ pInfo->ColorSpace = JPEG_GRAYSCALE_COLORSPACE;
+ }
+ else if ((hjpeg->Instance->CONFR1 & JPEG_CONFR1_NF) == JPEG_CONFR1_NF)
+ {
+ pInfo->ColorSpace = JPEG_CMYK_COLORSPACE;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ pInfo->ImageHeight = (hjpeg->Instance->CONFR1 & 0xFFFF0000UL) >> 16;
+ pInfo->ImageWidth = (hjpeg->Instance->CONFR3 & 0xFFFF0000UL) >> 16;
+
+ if ((pInfo->ColorSpace == JPEG_YCBCR_COLORSPACE) || (pInfo->ColorSpace == JPEG_CMYK_COLORSPACE))
+ {
+ yblockNb = (hjpeg->Instance->CONFR4 & JPEG_CONFR4_NB) >> 4;
+ cBblockNb = (hjpeg->Instance->CONFR5 & JPEG_CONFR5_NB) >> 4;
+ cRblockNb = (hjpeg->Instance->CONFR6 & JPEG_CONFR6_NB) >> 4;
+
+ if ((yblockNb == 1UL) && (cBblockNb == 0UL) && (cRblockNb == 0UL))
+ {
+ pInfo->ChromaSubsampling = JPEG_422_SUBSAMPLING; /*16x8 block*/
+ }
+ else if ((yblockNb == 0UL) && (cBblockNb == 0UL) && (cRblockNb == 0UL))
+ {
+ pInfo->ChromaSubsampling = JPEG_444_SUBSAMPLING;
+ }
+ else if ((yblockNb == 3UL) && (cBblockNb == 0UL) && (cRblockNb == 0UL))
+ {
+ pInfo->ChromaSubsampling = JPEG_420_SUBSAMPLING;
+ }
+ else /*Default is 4:4:4*/
+ {
+ pInfo->ChromaSubsampling = JPEG_444_SUBSAMPLING;
+ }
+ }
+ else
+ {
+ pInfo->ChromaSubsampling = JPEG_444_SUBSAMPLING;
+ }
+
+ pInfo->ImageQuality = JPEG_GetQuality(hjpeg);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable JPEG Header parsing for decoding
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for the JPEG.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_EnableHeaderParsing(JPEG_HandleTypeDef *hjpeg)
+{
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (hjpeg->State == HAL_JPEG_STATE_READY)
+ {
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_BUSY;
+
+ /* Enable header processing*/
+ hjpeg->Instance->CONFR1 |= JPEG_CONFR1_HDR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Disable JPEG Header parsing for decoding
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for the JPEG.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_DisableHeaderParsing(JPEG_HandleTypeDef *hjpeg)
+{
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (hjpeg->State == HAL_JPEG_STATE_READY)
+ {
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_BUSY;
+
+ /* Disable header processing*/
+ hjpeg->Instance->CONFR1 &= ~JPEG_CONFR1_HDR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Modify the default Quantization tables used for JPEG encoding.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param QTable0 pointer to uint8_t , define the user quantification table for color component 1.
+ * If NULL assume no need to update the table and no error return
+ * @param QTable1 pointer to uint8_t , define the user quantification table for color component 2.
+ * If NULL assume no need to update the table and no error return.
+ * @param QTable2 pointer to uint8_t , define the user quantification table for color component 3,
+ * If NULL assume no need to update the table and no error return.
+ * @param QTable3 pointer to uint8_t , define the user quantification table for color component 4.
+ * If NULL assume no need to update the table and no error return.
+ *
+ * @retval HAL status
+ */
+
+
+HAL_StatusTypeDef HAL_JPEG_SetUserQuantTables(JPEG_HandleTypeDef *hjpeg, uint8_t *QTable0, uint8_t *QTable1,
+ uint8_t *QTable2, uint8_t *QTable3)
+{
+ /* Process Locked */
+ __HAL_LOCK(hjpeg);
+
+ if (hjpeg->State == HAL_JPEG_STATE_READY)
+ {
+ /* Change the DMA state */
+ hjpeg->State = HAL_JPEG_STATE_BUSY;
+
+ hjpeg->Context |= JPEG_CONTEXT_CUSTOM_TABLES;
+
+ hjpeg->QuantTable0 = QTable0;
+ hjpeg->QuantTable1 = QTable1;
+ hjpeg->QuantTable2 = QTable2;
+ hjpeg->QuantTable3 = QTable3;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Change the DMA state */
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup JPEG_Exported_Functions_Group3 encoding/decoding processing functions
+ * @brief processing functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### JPEG processing functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) HAL_JPEG_Encode() : JPEG encoding with polling process
+ (+) HAL_JPEG_Decode() : JPEG decoding with polling process
+ (+) HAL_JPEG_Encode_IT() : JPEG encoding with interrupt process
+ (+) HAL_JPEG_Decode_IT() : JPEG decoding with interrupt process
+ (+) HAL_JPEG_Encode_DMA() : JPEG encoding with DMA process
+ (+) HAL_JPEG_Decode_DMA() : JPEG decoding with DMA process
+ (+) HAL_JPEG_Pause() : Pause the Input/Output processing
+ (+) HAL_JPEG_Resume() : Resume the JPEG Input/Output processing
+ (+) HAL_JPEG_ConfigInputBuffer() : Config Encoding/Decoding Input Buffer
+ (+) HAL_JPEG_ConfigOutputBuffer() : Config Encoding/Decoding Output Buffer
+ (+) HAL_JPEG_Abort() : Aborts the JPEG Encoding/Decoding
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Starts JPEG encoding with polling processing
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pDataInMCU Pointer to the Input buffer
+ * @param InDataLength size in bytes Input buffer
+ * @param pDataOut Pointer to the jpeg output data buffer
+ * @param OutDataLength size in bytes of the Output buffer
+ * @param Timeout Specify Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Encode(JPEG_HandleTypeDef *hjpeg, uint8_t *pDataInMCU, uint32_t InDataLength,
+ uint8_t *pDataOut, uint32_t OutDataLength, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param((InDataLength >= 4UL));
+ assert_param((OutDataLength >= 4UL));
+
+ /* Check In/out buffer allocation and size */
+ if ((hjpeg == NULL) || (pDataInMCU == NULL) || (pDataOut == NULL))
+ {
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hjpeg);
+
+ if (hjpeg->State != HAL_JPEG_STATE_READY)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_BUSY;
+ }
+
+ if (hjpeg->State == HAL_JPEG_STATE_READY)
+ {
+ if ((hjpeg->Context & JPEG_CONTEXT_CONF_ENCODING) == JPEG_CONTEXT_CONF_ENCODING)
+ {
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_BUSY_ENCODING;
+
+ /*Set the Context to Encode with Polling*/
+ hjpeg->Context &= ~(JPEG_CONTEXT_OPERATION_MASK | JPEG_CONTEXT_METHOD_MASK);
+ hjpeg->Context |= (JPEG_CONTEXT_ENCODE | JPEG_CONTEXT_POLLING);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /*Store In/out buffers pointers and size*/
+ hjpeg->pJpegInBuffPtr = pDataInMCU;
+ hjpeg->pJpegOutBuffPtr = pDataOut;
+ hjpeg->InDataLength = InDataLength - (InDataLength % 4UL); /* In Data length must be multiple of 4 Bytes (1 word)*/
+ hjpeg->OutDataLength = OutDataLength - (OutDataLength % 4UL); /* Out Data length must be multiple of 4 Bytes (1 word)*/
+
+ /*Reset In/out data counter */
+ hjpeg->JpegInCount = 0;
+ hjpeg->JpegOutCount = 0;
+
+ /*Init decoding process*/
+ JPEG_Init_Process(hjpeg);
+
+ /*JPEG data processing : In/Out FIFO transfer*/
+ while ((JPEG_Process(hjpeg) == JPEG_PROCESS_ONGOING))
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+ {
+
+ /* Update error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_ERROR;
+ }
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts JPEG decoding with polling processing
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pDataIn Pointer to the input data buffer
+ * @param InDataLength size in bytes Input buffer
+ * @param pDataOutMCU Pointer to the Output data buffer
+ * @param OutDataLength size in bytes of the Output buffer
+ * @param Timeout Specify Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Decode(JPEG_HandleTypeDef *hjpeg, uint8_t *pDataIn, uint32_t InDataLength,
+ uint8_t *pDataOutMCU, uint32_t OutDataLength, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param((InDataLength >= 4UL));
+ assert_param((OutDataLength >= 4UL));
+
+ /* Check In/out buffer allocation and size */
+ if ((hjpeg == NULL) || (pDataIn == NULL) || (pDataOutMCU == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hjpeg);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ if (hjpeg->State == HAL_JPEG_STATE_READY)
+ {
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_BUSY_DECODING;
+
+ /*Set the Context to Decode with Polling*/
+ /*Set the Context to Encode with Polling*/
+ hjpeg->Context &= ~(JPEG_CONTEXT_OPERATION_MASK | JPEG_CONTEXT_METHOD_MASK);
+ hjpeg->Context |= (JPEG_CONTEXT_DECODE | JPEG_CONTEXT_POLLING);
+
+ /*Store In/out buffers pointers and size*/
+ hjpeg->pJpegInBuffPtr = pDataIn;
+ hjpeg->pJpegOutBuffPtr = pDataOutMCU;
+ hjpeg->InDataLength = InDataLength - (InDataLength % 4UL); /*In Data length must be multiple of 4 Bytes (1 word)*/
+ hjpeg->OutDataLength = OutDataLength - (OutDataLength % 4UL); /*Out Data length must be multiple of 4 Bytes (1 word)*/
+
+ /*Reset In/out data counter */
+ hjpeg->JpegInCount = 0;
+ hjpeg->JpegOutCount = 0;
+
+ /*Init decoding process*/
+ JPEG_Init_Process(hjpeg);
+
+ /*JPEG data processing : In/Out FIFO transfer*/
+ while ((JPEG_Process(hjpeg) == JPEG_PROCESS_ONGOING))
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+ {
+
+ /* Update error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_BUSY;
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts JPEG encoding with interrupt processing
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pDataInMCU Pointer to the Input buffer
+ * @param InDataLength size in bytes Input buffer
+ * @param pDataOut Pointer to the jpeg output data buffer
+ * @param OutDataLength size in bytes of the Output buffer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Encode_IT(JPEG_HandleTypeDef *hjpeg, uint8_t *pDataInMCU, uint32_t InDataLength,
+ uint8_t *pDataOut, uint32_t OutDataLength)
+{
+ /* Check the parameters */
+ assert_param((InDataLength >= 4UL));
+ assert_param((OutDataLength >= 4UL));
+
+ /* Check In/out buffer allocation and size */
+ if ((hjpeg == NULL) || (pDataInMCU == NULL) || (pDataOut == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hjpeg);
+
+ if (hjpeg->State != HAL_JPEG_STATE_READY)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_BUSY;
+ }
+ else
+ {
+ if ((hjpeg->Context & JPEG_CONTEXT_CONF_ENCODING) == JPEG_CONTEXT_CONF_ENCODING)
+ {
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_BUSY_ENCODING;
+
+ /*Set the Context to Encode with IT*/
+ hjpeg->Context &= ~(JPEG_CONTEXT_OPERATION_MASK | JPEG_CONTEXT_METHOD_MASK);
+ hjpeg->Context |= (JPEG_CONTEXT_ENCODE | JPEG_CONTEXT_IT);
+
+ /*Store In/out buffers pointers and size*/
+ hjpeg->pJpegInBuffPtr = pDataInMCU;
+ hjpeg->pJpegOutBuffPtr = pDataOut;
+ hjpeg->InDataLength = InDataLength - (InDataLength % 4UL); /*In Data length must be multiple of 4 Bytes (1 word)*/
+ hjpeg->OutDataLength = OutDataLength - (OutDataLength % 4UL); /*Out Data length must be multiple of 4 Bytes (1 word)*/
+
+ /*Reset In/out data counter */
+ hjpeg->JpegInCount = 0;
+ hjpeg->JpegOutCount = 0;
+
+ /*Init decoding process*/
+ JPEG_Init_Process(hjpeg);
+
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_ERROR;
+ }
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts JPEG decoding with interrupt processing
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pDataIn Pointer to the input data buffer
+ * @param InDataLength size in bytes Input buffer
+ * @param pDataOutMCU Pointer to the Output data buffer
+ * @param OutDataLength size in bytes of the Output buffer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Decode_IT(JPEG_HandleTypeDef *hjpeg, uint8_t *pDataIn, uint32_t InDataLength,
+ uint8_t *pDataOutMCU, uint32_t OutDataLength)
+{
+ /* Check the parameters */
+ assert_param((InDataLength >= 4UL));
+ assert_param((OutDataLength >= 4UL));
+
+ /* Check In/out buffer allocation and size */
+ if ((hjpeg == NULL) || (pDataIn == NULL) || (pDataOutMCU == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hjpeg);
+
+ if (hjpeg->State == HAL_JPEG_STATE_READY)
+ {
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_BUSY_DECODING;
+
+ /*Set the Context to Decode with IT*/
+ hjpeg->Context &= ~(JPEG_CONTEXT_OPERATION_MASK | JPEG_CONTEXT_METHOD_MASK);
+ hjpeg->Context |= (JPEG_CONTEXT_DECODE | JPEG_CONTEXT_IT);
+
+ /*Store In/out buffers pointers and size*/
+ hjpeg->pJpegInBuffPtr = pDataIn;
+ hjpeg->pJpegOutBuffPtr = pDataOutMCU;
+ hjpeg->InDataLength = InDataLength - (InDataLength % 4UL); /*In Data length must be multiple of 4 Bytes (1 word)*/
+ hjpeg->OutDataLength = OutDataLength - (OutDataLength % 4UL); /*Out Data length must be multiple of 4 Bytes (1 word)*/
+
+ /*Reset In/out data counter */
+ hjpeg->JpegInCount = 0;
+ hjpeg->JpegOutCount = 0;
+
+ /*Init decoding process*/
+ JPEG_Init_Process(hjpeg);
+
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_BUSY;
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts JPEG encoding with DMA processing
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pDataInMCU Pointer to the Input buffer
+ * @param InDataLength size in bytes Input buffer
+ * @param pDataOut Pointer to the jpeg output data buffer
+ * @param OutDataLength size in bytes of the Output buffer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Encode_DMA(JPEG_HandleTypeDef *hjpeg, uint8_t *pDataInMCU, uint32_t InDataLength,
+ uint8_t *pDataOut, uint32_t OutDataLength)
+{
+ /* Check the parameters */
+ assert_param((InDataLength >= 4UL));
+ assert_param((OutDataLength >= 4UL));
+
+ /* Check In/out buffer allocation and size */
+ if ((hjpeg == NULL) || (pDataInMCU == NULL) || (pDataOut == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hjpeg);
+
+ if (hjpeg->State != HAL_JPEG_STATE_READY)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_BUSY;
+ }
+ else
+ {
+ if ((hjpeg->Context & JPEG_CONTEXT_CONF_ENCODING) == JPEG_CONTEXT_CONF_ENCODING)
+ {
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_BUSY_ENCODING;
+
+ /*Set the Context to Encode with DMA*/
+ hjpeg->Context &= ~(JPEG_CONTEXT_OPERATION_MASK | JPEG_CONTEXT_METHOD_MASK);
+ hjpeg->Context |= (JPEG_CONTEXT_ENCODE | JPEG_CONTEXT_DMA);
+
+ /*Store In/out buffers pointers and size*/
+ hjpeg->pJpegInBuffPtr = pDataInMCU;
+ hjpeg->pJpegOutBuffPtr = pDataOut;
+ hjpeg->InDataLength = InDataLength;
+ hjpeg->OutDataLength = OutDataLength;
+
+ /*Reset In/out data counter */
+ hjpeg->JpegInCount = 0;
+ hjpeg->JpegOutCount = 0;
+
+ /*Init decoding process*/
+ JPEG_Init_Process(hjpeg);
+
+ /* JPEG encoding process using DMA */
+ if (JPEG_DMA_StartProcess(hjpeg) != HAL_OK)
+ {
+ /* Update State */
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_ERROR;
+ }
+
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_ERROR;
+ }
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts JPEG decoding with DMA processing
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pDataIn Pointer to the input data buffer
+ * @param InDataLength size in bytes Input buffer
+ * @param pDataOutMCU Pointer to the Output data buffer
+ * @param OutDataLength size in bytes of the Output buffer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Decode_DMA(JPEG_HandleTypeDef *hjpeg, uint8_t *pDataIn, uint32_t InDataLength,
+ uint8_t *pDataOutMCU, uint32_t OutDataLength)
+{
+ /* Check the parameters */
+ assert_param((InDataLength >= 4UL));
+ assert_param((OutDataLength >= 4UL));
+
+ /* Check In/out buffer allocation and size */
+ if ((hjpeg == NULL) || (pDataIn == NULL) || (pDataOutMCU == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hjpeg);
+
+ if (hjpeg->State == HAL_JPEG_STATE_READY)
+ {
+ /*Change JPEG state*/
+ hjpeg->State = HAL_JPEG_STATE_BUSY_DECODING;
+
+ /*Set the Context to Decode with DMA*/
+ hjpeg->Context &= ~(JPEG_CONTEXT_OPERATION_MASK | JPEG_CONTEXT_METHOD_MASK);
+ hjpeg->Context |= (JPEG_CONTEXT_DECODE | JPEG_CONTEXT_DMA);
+
+ /*Store In/out buffers pointers and size*/
+ hjpeg->pJpegInBuffPtr = pDataIn;
+ hjpeg->pJpegOutBuffPtr = pDataOutMCU;
+ hjpeg->InDataLength = InDataLength;
+ hjpeg->OutDataLength = OutDataLength;
+
+ /*Reset In/out data counter */
+ hjpeg->JpegInCount = 0;
+ hjpeg->JpegOutCount = 0;
+
+ /*Init decoding process*/
+ JPEG_Init_Process(hjpeg);
+
+ /* JPEG decoding process using DMA */
+ if (JPEG_DMA_StartProcess(hjpeg) != HAL_OK)
+ {
+ /* Update State */
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ return HAL_BUSY;
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Pause the JPEG Input/Output processing
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param XferSelection This parameter can be one of the following values :
+ * JPEG_PAUSE_RESUME_INPUT : Pause Input processing
+ * JPEG_PAUSE_RESUME_OUTPUT: Pause Output processing
+ * JPEG_PAUSE_RESUME_INPUT_OUTPUT: Pause Input and Output processing
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Pause(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection)
+{
+ uint32_t mask = 0;
+
+ assert_param(IS_JPEG_PAUSE_RESUME_STATE(XferSelection));
+
+ if ((hjpeg->Context & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_DMA)
+ {
+ if ((XferSelection & JPEG_PAUSE_RESUME_INPUT) == JPEG_PAUSE_RESUME_INPUT)
+ {
+ hjpeg->Context |= JPEG_CONTEXT_PAUSE_INPUT;
+ }
+ if ((XferSelection & JPEG_PAUSE_RESUME_OUTPUT) == JPEG_PAUSE_RESUME_OUTPUT)
+ {
+ hjpeg->Context |= JPEG_CONTEXT_PAUSE_OUTPUT;
+ }
+
+ }
+ else if ((hjpeg->Context & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_IT)
+ {
+
+ if ((XferSelection & JPEG_PAUSE_RESUME_INPUT) == JPEG_PAUSE_RESUME_INPUT)
+ {
+ hjpeg->Context |= JPEG_CONTEXT_PAUSE_INPUT;
+ mask |= (JPEG_IT_IFT | JPEG_IT_IFNF);
+ }
+ if ((XferSelection & JPEG_PAUSE_RESUME_OUTPUT) == JPEG_PAUSE_RESUME_OUTPUT)
+ {
+ hjpeg->Context |= JPEG_CONTEXT_PAUSE_OUTPUT;
+ mask |= (JPEG_IT_OFT | JPEG_IT_OFNE | JPEG_IT_EOC);
+ }
+ __HAL_JPEG_DISABLE_IT(hjpeg, mask);
+
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the JPEG Input/Output processing
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param XferSelection This parameter can be one of the following values :
+ * JPEG_PAUSE_RESUME_INPUT : Resume Input processing
+ * JPEG_PAUSE_RESUME_OUTPUT: Resume Output processing
+ * JPEG_PAUSE_RESUME_INPUT_OUTPUT: Resume Input and Output processing
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Resume(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection)
+{
+ uint32_t mask = 0;
+ uint32_t xfrSize;
+
+ assert_param(IS_JPEG_PAUSE_RESUME_STATE(XferSelection));
+
+ if ((hjpeg->Context & (JPEG_CONTEXT_PAUSE_INPUT | JPEG_CONTEXT_PAUSE_OUTPUT)) == 0UL)
+ {
+ /* if nothing paused to resume return error*/
+ return HAL_ERROR;
+ }
+
+ if ((hjpeg->Context & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_DMA)
+ {
+
+ if ((XferSelection & JPEG_PAUSE_RESUME_INPUT) == JPEG_PAUSE_RESUME_INPUT)
+ {
+ hjpeg->Context &= (~JPEG_CONTEXT_PAUSE_INPUT);
+ /*if the MDMA In is triggred with JPEG In FIFO Threshold flag
+ then MDMA In buffer size is 32 bytes
+
+ else (MDMA In is triggred with JPEG In FIFO not full flag)
+ then MDMA In buffer size is 4 bytes
+ */
+ xfrSize = hjpeg->hdmain->Init.BufferTransferLength;
+
+ if (xfrSize == 0UL)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+ return HAL_ERROR;
+ }
+ /*MDMA transfer size (BNDTR) must be a multiple of MDMA buffer size (TLEN)*/
+ hjpeg->InDataLength = hjpeg->InDataLength - (hjpeg->InDataLength % xfrSize);
+
+
+ if (hjpeg->InDataLength > 0UL)
+ {
+ /* Start DMA FIFO In transfer */
+ if (HAL_MDMA_Start_IT(hjpeg->hdmain, (uint32_t)hjpeg->pJpegInBuffPtr, (uint32_t)&hjpeg->Instance->DIR,
+ hjpeg->InDataLength, 1) != HAL_OK)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+ return HAL_ERROR;
+ }
+ }
+ }
+ if ((XferSelection & JPEG_PAUSE_RESUME_OUTPUT) == JPEG_PAUSE_RESUME_OUTPUT)
+ {
+ hjpeg->Context &= (~JPEG_CONTEXT_PAUSE_OUTPUT);
+
+ if ((hjpeg->Context & JPEG_CONTEXT_ENDING_DMA) != 0UL)
+ {
+ JPEG_DMA_PollResidualData(hjpeg);
+ }
+ else
+ {
+ /*if the MDMA Out is triggred with JPEG Out FIFO Threshold flag
+ then MDMA out buffer size is 32 bytes
+ else (MDMA Out is triggred with JPEG Out FIFO not empty flag)
+ then MDMA buffer size is 4 bytes
+ */
+ xfrSize = hjpeg->hdmaout->Init.BufferTransferLength;
+
+ if (xfrSize == 0UL)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+ return HAL_ERROR;
+ }
+ /*MDMA transfer size (BNDTR) must be a multiple of MDMA buffer size (TLEN)*/
+ hjpeg->OutDataLength = hjpeg->OutDataLength - (hjpeg->OutDataLength % xfrSize);
+
+ /* Start DMA FIFO Out transfer */
+ if (HAL_MDMA_Start_IT(hjpeg->hdmaout, (uint32_t)&hjpeg->Instance->DOR, (uint32_t)hjpeg->pJpegOutBuffPtr,
+ hjpeg->OutDataLength, 1) != HAL_OK)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+ return HAL_ERROR;
+ }
+ }
+
+ }
+
+ }
+ else if ((hjpeg->Context & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_IT)
+ {
+ if ((XferSelection & JPEG_PAUSE_RESUME_INPUT) == JPEG_PAUSE_RESUME_INPUT)
+ {
+ hjpeg->Context &= (~JPEG_CONTEXT_PAUSE_INPUT);
+ mask |= (JPEG_IT_IFT | JPEG_IT_IFNF);
+ }
+ if ((XferSelection & JPEG_PAUSE_RESUME_OUTPUT) == JPEG_PAUSE_RESUME_OUTPUT)
+ {
+ hjpeg->Context &= (~JPEG_CONTEXT_PAUSE_OUTPUT);
+ mask |= (JPEG_IT_OFT | JPEG_IT_OFNE | JPEG_IT_EOC);
+ }
+ __HAL_JPEG_ENABLE_IT(hjpeg, mask);
+
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Config Encoding/Decoding Input Buffer.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module.
+ * @param pNewInputBuffer Pointer to the new input data buffer
+ * @param InDataLength Size in bytes of the new Input data buffer
+ * @retval HAL status
+ */
+void HAL_JPEG_ConfigInputBuffer(JPEG_HandleTypeDef *hjpeg, uint8_t *pNewInputBuffer, uint32_t InDataLength)
+{
+ hjpeg->pJpegInBuffPtr = pNewInputBuffer;
+ hjpeg->InDataLength = InDataLength;
+}
+
+/**
+ * @brief Config Encoding/Decoding Output Buffer.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module.
+ * @param pNewOutputBuffer Pointer to the new output data buffer
+ * @param OutDataLength Size in bytes of the new Output data buffer
+ * @retval HAL status
+ */
+void HAL_JPEG_ConfigOutputBuffer(JPEG_HandleTypeDef *hjpeg, uint8_t *pNewOutputBuffer, uint32_t OutDataLength)
+{
+ hjpeg->pJpegOutBuffPtr = pNewOutputBuffer;
+ hjpeg->OutDataLength = OutDataLength;
+}
+
+/**
+ * @brief Aborts the JPEG Encoding/Decoding.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_JPEG_Abort(JPEG_HandleTypeDef *hjpeg)
+{
+ uint32_t tickstart;
+ uint32_t tmpContext;
+ tmpContext = hjpeg->Context;
+
+ /*Reset the Context operation and method*/
+ hjpeg->Context &= ~(JPEG_CONTEXT_OPERATION_MASK | JPEG_CONTEXT_METHOD_MASK | JPEG_CONTEXT_ENDING_DMA);
+
+ if ((tmpContext & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_DMA)
+ {
+ /* Stop the DMA In/out Xfer*/
+ if (HAL_MDMA_Abort(hjpeg->hdmaout) != HAL_OK)
+ {
+ if (hjpeg->hdmaout->ErrorCode == HAL_MDMA_ERROR_TIMEOUT)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ }
+ }
+ if (HAL_MDMA_Abort(hjpeg->hdmain) != HAL_OK)
+ {
+ if (hjpeg->hdmain->ErrorCode == HAL_MDMA_ERROR_TIMEOUT)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ }
+ }
+
+ }
+
+ /* Stop the JPEG encoding/decoding process*/
+ hjpeg->Instance->CONFR0 &= ~JPEG_CONFR0_START;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check if the JPEG Codec is effectively disabled */
+ while (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_COF) != 0UL)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > JPEG_TIMEOUT_VALUE)
+ {
+ /* Update error code */
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_TIMEOUT;
+
+ /* Change the DMA state */
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+ break;
+ }
+ }
+
+ /* Disable All Interrupts */
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_INTERRUPT_MASK);
+
+
+ /* Flush input and output FIFOs*/
+ hjpeg->Instance->CR |= JPEG_CR_IFF;
+ hjpeg->Instance->CR |= JPEG_CR_OFF;
+
+ /* Clear all flags */
+ __HAL_JPEG_CLEAR_FLAG(hjpeg, JPEG_FLAG_ALL);
+
+ /* Reset JpegInCount and JpegOutCount */
+ hjpeg->JpegInCount = 0;
+ hjpeg->JpegOutCount = 0;
+
+ /*Reset the Context Pause*/
+ hjpeg->Context &= ~(JPEG_CONTEXT_PAUSE_INPUT | JPEG_CONTEXT_PAUSE_OUTPUT);
+
+ /* Change the DMA state*/
+ if (hjpeg->ErrorCode != HAL_JPEG_ERROR_NONE)
+ {
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+ /* Return function status */
+ return HAL_ERROR;
+ }
+ else
+ {
+ hjpeg->State = HAL_JPEG_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+ /* Return function status */
+ return HAL_OK;
+ }
+
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup JPEG_Exported_Functions_Group4 JPEG Decode/Encode callback functions
+ * @brief JPEG process callback functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### JPEG Decode and Encode callback functions #####
+ ==============================================================================
+ [..] This section provides callback functions:
+ (+) HAL_JPEG_InfoReadyCallback() : Decoding JPEG Info ready callback
+ (+) HAL_JPEG_EncodeCpltCallback() : Encoding complete callback.
+ (+) HAL_JPEG_DecodeCpltCallback() : Decoding complete callback.
+ (+) HAL_JPEG_ErrorCallback() : JPEG error callback.
+ (+) HAL_JPEG_GetDataCallback() : Get New Data chunk callback.
+ (+) HAL_JPEG_DataReadyCallback() : Decoded/Encoded Data ready callback.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Decoding JPEG Info ready callback.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pInfo pointer to a JPEG_ConfTypeDef structure that contains
+ * The JPEG decoded header informations
+ * @retval None
+ */
+__weak void HAL_JPEG_InfoReadyCallback(JPEG_HandleTypeDef *hjpeg, JPEG_ConfTypeDef *pInfo)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hjpeg);
+ UNUSED(pInfo);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_JPEG_HeaderParsingCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Encoding complete callback.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+__weak void HAL_JPEG_EncodeCpltCallback(JPEG_HandleTypeDef *hjpeg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hjpeg);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_JPEG_EncodeCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Decoding complete callback.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+__weak void HAL_JPEG_DecodeCpltCallback(JPEG_HandleTypeDef *hjpeg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hjpeg);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_JPEG_EncodeCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief JPEG error callback.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+__weak void HAL_JPEG_ErrorCallback(JPEG_HandleTypeDef *hjpeg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hjpeg);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_JPEG_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Get New Data chunk callback.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param NbDecodedData Number of consummed data in the previous chunk in bytes
+ * @retval None
+ */
+__weak void HAL_JPEG_GetDataCallback(JPEG_HandleTypeDef *hjpeg, uint32_t NbDecodedData)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hjpeg);
+ UNUSED(NbDecodedData);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_JPEG_GetDataCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Decoded/Encoded Data ready callback.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param pDataOut pointer to the output data buffer
+ * @param OutDataLength number in bytes of data available in the specified output buffer
+ * @retval None
+ */
+__weak void HAL_JPEG_DataReadyCallback(JPEG_HandleTypeDef *hjpeg, uint8_t *pDataOut, uint32_t OutDataLength)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hjpeg);
+ UNUSED(pDataOut);
+ UNUSED(OutDataLength);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_JPEG_DataReadyCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+
+/** @defgroup JPEG_Exported_Functions_Group5 JPEG IRQ handler management
+ * @brief JPEG IRQ handler.
+ *
+@verbatim
+ ==============================================================================
+ ##### JPEG IRQ handler management #####
+ ==============================================================================
+ [..] This section provides JPEG IRQ handler function.
+ (+) HAL_JPEG_IRQHandler() : handles JPEG interrupt request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function handles JPEG interrupt request.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+void HAL_JPEG_IRQHandler(JPEG_HandleTypeDef *hjpeg)
+{
+ switch (hjpeg->State)
+ {
+ case HAL_JPEG_STATE_BUSY_ENCODING:
+ case HAL_JPEG_STATE_BUSY_DECODING:
+ /* continue JPEG data encoding/Decoding*/
+ /* JPEG data processing : In/Out FIFO transfer*/
+ if ((hjpeg->Context & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_IT)
+ {
+ (void) JPEG_Process(hjpeg);
+ }
+ else if ((hjpeg->Context & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_DMA)
+ {
+ JPEG_DMA_ContinueProcess(hjpeg);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup JPEG_Exported_Functions_Group6 Peripheral State functions
+ * @brief Peripheral State functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Error functions #####
+ ==============================================================================
+ [..] This section provides JPEG State and Errors function.
+ (+) HAL_JPEG_GetState() : permits to get in run-time the JPEG state.
+ (+) HAL_JPEG_GetError() : Returns the JPEG error code if any.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the JPEG state.
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval JPEG state
+ */
+HAL_JPEG_STATETypeDef HAL_JPEG_GetState(JPEG_HandleTypeDef *hjpeg)
+{
+ return hjpeg->State;
+}
+
+/**
+ * @brief Return the JPEG error code
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for the specified JPEG.
+ * @retval JPEG Error Code
+ */
+uint32_t HAL_JPEG_GetError(JPEG_HandleTypeDef *hjpeg)
+{
+ return hjpeg->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup JPEG_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Generates Huffman sizes/Codes Table from Bits/vals Table
+ * @param Bits pointer to bits table
+ * @param Huffsize pointer to sizes table
+ * @param Huffcode pointer to codes table
+ * @param LastK pointer to last Coeff (table dimmension)
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef JPEG_Bits_To_SizeCodes(uint8_t *Bits, uint8_t *Huffsize, uint32_t *Huffcode, uint32_t *LastK)
+{
+ uint32_t i;
+ uint32_t p;
+ uint32_t l;
+ uint32_t code;
+ uint32_t si;
+
+ /* Figure C.1: Generation of table of Huffman code sizes */
+ p = 0;
+ for (l = 0; l < 16UL; l++)
+ {
+ i = (uint32_t)Bits[l];
+ if ((p + i) > 256UL)
+ {
+ /* check for table overflow */
+ return HAL_ERROR;
+ }
+ while (i != 0UL)
+ {
+ Huffsize[p] = (uint8_t) l + 1U;
+ p++;
+ i--;
+ }
+ }
+ Huffsize[p] = 0;
+ *LastK = p;
+
+ /* Figure C.2: Generation of table of Huffman codes */
+ code = 0;
+ si = Huffsize[0];
+ p = 0;
+ while (Huffsize[p] != 0U)
+ {
+ while (((uint32_t) Huffsize[p]) == si)
+ {
+ Huffcode[p] = code;
+ p++;
+ code++;
+ }
+ /* code must fit in "size" bits (si), no code is allowed to be all ones*/
+ if(si > 31UL)
+ {
+ return HAL_ERROR;
+ }
+ if (((uint32_t) code) >= (((uint32_t) 1) << si))
+ {
+ return HAL_ERROR;
+ }
+ code <<= 1;
+ si++;
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Transform a Bits/Vals AC Huffman table to sizes/Codes huffman Table
+ * that can programmed to the JPEG encoder registers
+ * @param AC_BitsValsTable pointer to AC huffman bits/vals table
+ * @param AC_SizeCodesTable pointer to AC huffman Sizes/Codes table
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef JPEG_ACHuff_BitsVals_To_SizeCodes(JPEG_ACHuffTableTypeDef *AC_BitsValsTable,
+ JPEG_AC_HuffCodeTableTypeDef *AC_SizeCodesTable)
+{
+ HAL_StatusTypeDef error;
+ uint8_t huffsize[257];
+ uint32_t huffcode[257];
+ uint32_t k;
+ uint32_t l, lsb, msb;
+ uint32_t lastK;
+
+ error = JPEG_Bits_To_SizeCodes(AC_BitsValsTable->Bits, huffsize, huffcode, &lastK);
+ if (error != HAL_OK)
+ {
+ return error;
+ }
+
+ /* Figure C.3: Ordering procedure for encoding procedure code tables */
+ k = 0;
+
+ while (k < lastK)
+ {
+ l = AC_BitsValsTable->HuffVal[k];
+ if (l == 0UL)
+ {
+ l = 160; /*l = 0x00 EOB code*/
+ }
+ else if (l == 0xF0UL) /* l = 0xF0 ZRL code*/
+ {
+ l = 161;
+ }
+ else
+ {
+ msb = (l & 0xF0UL) >> 4;
+ lsb = (l & 0x0FUL);
+ l = (msb * 10UL) + lsb - 1UL;
+ }
+ if (l >= JPEG_AC_HUFF_TABLE_SIZE)
+ {
+ return HAL_ERROR; /* Huffman Table overflow error*/
+ }
+ else
+ {
+ AC_SizeCodesTable->HuffmanCode[l] = huffcode[k];
+ AC_SizeCodesTable->CodeLength[l] = huffsize[k] - 1U;
+ k++;
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Transform a Bits/Vals DC Huffman table to sizes/Codes huffman Table
+ * that can programmed to the JPEG encoder registers
+ * @param DC_BitsValsTable pointer to DC huffman bits/vals table
+ * @param DC_SizeCodesTable pointer to DC huffman Sizes/Codes table
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef JPEG_DCHuff_BitsVals_To_SizeCodes(JPEG_DCHuffTableTypeDef *DC_BitsValsTable,
+ JPEG_DC_HuffCodeTableTypeDef *DC_SizeCodesTable)
+{
+ HAL_StatusTypeDef error;
+
+ uint32_t k;
+ uint32_t l;
+ uint32_t lastK;
+ uint8_t huffsize[257];
+ uint32_t huffcode[257];
+ error = JPEG_Bits_To_SizeCodes(DC_BitsValsTable->Bits, huffsize, huffcode, &lastK);
+ if (error != HAL_OK)
+ {
+ return error;
+ }
+ /* Figure C.3: ordering procedure for encoding procedure code tables */
+ k = 0;
+
+ while (k < lastK)
+ {
+ l = DC_BitsValsTable->HuffVal[k];
+ if (l >= JPEG_DC_HUFF_TABLE_SIZE)
+ {
+ return HAL_ERROR; /* Huffman Table overflow error*/
+ }
+ else
+ {
+ DC_SizeCodesTable->HuffmanCode[l] = huffcode[k];
+ DC_SizeCodesTable->CodeLength[l] = huffsize[k] - 1U;
+ k++;
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the JPEG register with an DC huffman table at the given DC table address
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param HuffTableDC pointer to DC huffman table
+ * @param DCTableAddress Encoder DC huffman table address it could be HUFFENC_DC0 or HUFFENC_DC1.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef JPEG_Set_HuffDC_Mem(JPEG_HandleTypeDef *hjpeg, JPEG_DCHuffTableTypeDef *HuffTableDC,
+ const __IO uint32_t *DCTableAddress)
+{
+ HAL_StatusTypeDef error;
+ JPEG_DC_HuffCodeTableTypeDef dcSizeCodesTable;
+ uint32_t i;
+ uint32_t lsb;
+ uint32_t msb;
+ __IO uint32_t *address, *addressDef;
+
+ if (DCTableAddress == (hjpeg->Instance->HUFFENC_DC0))
+ {
+ address = (hjpeg->Instance->HUFFENC_DC0 + (JPEG_DC_HUFF_TABLE_SIZE / 2UL));
+ }
+ else if (DCTableAddress == (hjpeg->Instance->HUFFENC_DC1))
+ {
+ address = (hjpeg->Instance->HUFFENC_DC1 + (JPEG_DC_HUFF_TABLE_SIZE / 2UL));
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ if (HuffTableDC != NULL)
+ {
+ error = JPEG_DCHuff_BitsVals_To_SizeCodes(HuffTableDC, &dcSizeCodesTable);
+ if (error != HAL_OK)
+ {
+ return error;
+ }
+ addressDef = address;
+ *addressDef = 0x0FFF0FFF;
+ addressDef++;
+ *addressDef = 0x0FFF0FFF;
+
+ i = JPEG_DC_HUFF_TABLE_SIZE;
+ while (i > 1UL)
+ {
+ i--;
+ address --;
+ msb = ((uint32_t)(((uint32_t)dcSizeCodesTable.CodeLength[i] & 0xFU) << 8)) | ((uint32_t)dcSizeCodesTable.HuffmanCode[i] &
+ 0xFFUL);
+ i--;
+ lsb = ((uint32_t)(((uint32_t)dcSizeCodesTable.CodeLength[i] & 0xFU) << 8)) | ((uint32_t)dcSizeCodesTable.HuffmanCode[i] &
+ 0xFFUL);
+
+ *address = lsb | (msb << 16);
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the JPEG register with an AC huffman table at the given AC table address
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param HuffTableAC pointer to AC huffman table
+ * @param ACTableAddress Encoder AC huffman table address it could be HUFFENC_AC0 or HUFFENC_AC1.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef JPEG_Set_HuffAC_Mem(JPEG_HandleTypeDef *hjpeg, JPEG_ACHuffTableTypeDef *HuffTableAC,
+ const __IO uint32_t *ACTableAddress)
+{
+ HAL_StatusTypeDef error;
+ JPEG_AC_HuffCodeTableTypeDef acSizeCodesTable;
+ uint32_t i, lsb, msb;
+ __IO uint32_t *address, *addressDef;
+
+ if (ACTableAddress == (hjpeg->Instance->HUFFENC_AC0))
+ {
+ address = (hjpeg->Instance->HUFFENC_AC0 + (JPEG_AC_HUFF_TABLE_SIZE / 2UL));
+ }
+ else if (ACTableAddress == (hjpeg->Instance->HUFFENC_AC1))
+ {
+ address = (hjpeg->Instance->HUFFENC_AC1 + (JPEG_AC_HUFF_TABLE_SIZE / 2UL));
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ if (HuffTableAC != NULL)
+ {
+ error = JPEG_ACHuff_BitsVals_To_SizeCodes(HuffTableAC, &acSizeCodesTable);
+ if (error != HAL_OK)
+ {
+ return error;
+ }
+ /* Default values settings: 162:167 FFFh , 168:175 FD0h_FD7h */
+ /* Locations 162:175 of each AC table contain information used internally by the core */
+
+ addressDef = address;
+ for (i = 0; i < 3UL; i++)
+ {
+ *addressDef = 0x0FFF0FFF;
+ addressDef++;
+ }
+ *addressDef = 0x0FD10FD0;
+ addressDef++;
+ *addressDef = 0x0FD30FD2;
+ addressDef++;
+ *addressDef = 0x0FD50FD4;
+ addressDef++;
+ *addressDef = 0x0FD70FD6;
+ /* end of Locations 162:175 */
+
+
+ i = JPEG_AC_HUFF_TABLE_SIZE;
+ while (i > 1UL)
+ {
+ i--;
+ address--;
+ msb = ((uint32_t)(((uint32_t)acSizeCodesTable.CodeLength[i] & 0xFU) << 8)) | ((uint32_t)acSizeCodesTable.HuffmanCode[i] &
+ 0xFFUL);
+ i--;
+ lsb = ((uint32_t)(((uint32_t)acSizeCodesTable.CodeLength[i] & 0xFU) << 8)) | ((uint32_t)acSizeCodesTable.HuffmanCode[i] &
+ 0xFFUL);
+
+ *address = lsb | (msb << 16);
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the JPEG encoder register huffman tables to used during
+ * the encdoing operation
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+static HAL_StatusTypeDef JPEG_Set_HuffEnc_Mem(JPEG_HandleTypeDef *hjpeg)
+{
+ HAL_StatusTypeDef error;
+
+ JPEG_Set_Huff_DHTMem(hjpeg);
+ error = JPEG_Set_HuffAC_Mem(hjpeg, (JPEG_ACHuffTableTypeDef *)(uint32_t)&JPEG_ACLUM_HuffTable,
+ (hjpeg->Instance->HUFFENC_AC0));
+ if (error != HAL_OK)
+ {
+ return error;
+ }
+
+ error = JPEG_Set_HuffAC_Mem(hjpeg, (JPEG_ACHuffTableTypeDef *)(uint32_t)&JPEG_ACCHROM_HuffTable,
+ (hjpeg->Instance->HUFFENC_AC1));
+ if (error != HAL_OK)
+ {
+ return error;
+ }
+
+ error = JPEG_Set_HuffDC_Mem(hjpeg, (JPEG_DCHuffTableTypeDef *)(uint32_t)&JPEG_DCLUM_HuffTable,
+ hjpeg->Instance->HUFFENC_DC0);
+ if (error != HAL_OK)
+ {
+ return error;
+ }
+
+ error = JPEG_Set_HuffDC_Mem(hjpeg, (JPEG_DCHuffTableTypeDef *)(uint32_t)&JPEG_DCCHROM_HuffTable,
+ hjpeg->Instance->HUFFENC_DC1);
+ if (error != HAL_OK)
+ {
+ return error;
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the JPEG register huffman tables to be included in the JPEG
+ * file header (used for encoding only)
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+static void JPEG_Set_Huff_DHTMem(JPEG_HandleTypeDef *hjpeg)
+{
+ JPEG_ACHuffTableTypeDef *HuffTableAC0 = (JPEG_ACHuffTableTypeDef *)(uint32_t)&JPEG_ACLUM_HuffTable;
+ JPEG_ACHuffTableTypeDef *HuffTableAC1 = (JPEG_ACHuffTableTypeDef *)(uint32_t)&JPEG_ACCHROM_HuffTable;
+ JPEG_DCHuffTableTypeDef *HuffTableDC0 = (JPEG_DCHuffTableTypeDef *)(uint32_t)&JPEG_DCLUM_HuffTable;
+ JPEG_DCHuffTableTypeDef *HuffTableDC1 = (JPEG_DCHuffTableTypeDef *)(uint32_t)&JPEG_DCCHROM_HuffTable;
+ uint32_t value, index;
+ __IO uint32_t *address;
+
+ /* DC0 Huffman Table : BITS*/
+ /* DC0 BITS is a 16 Bytes table i.e 4x32bits words from DHTMEM base address to DHTMEM + 3*/
+ address = (hjpeg->Instance->DHTMEM + 3);
+ index = 16;
+ while (index > 3UL)
+ {
+
+ *address = (((uint32_t)HuffTableDC0->Bits[index - 1UL] & 0xFFUL) << 24) |
+ (((uint32_t)HuffTableDC0->Bits[index - 2UL] & 0xFFUL) << 16) |
+ (((uint32_t)HuffTableDC0->Bits[index - 3UL] & 0xFFUL) << 8) |
+ ((uint32_t)HuffTableDC0->Bits[index - 4UL] & 0xFFUL);
+ address--;
+ index -= 4UL;
+
+ }
+ /* DC0 Huffman Table : Val*/
+ /* DC0 VALS is a 12 Bytes table i.e 3x32bits words from DHTMEM base address +4 to DHTMEM + 6 */
+ address = (hjpeg->Instance->DHTMEM + 6);
+ index = 12;
+ while (index > 3UL)
+ {
+ *address = (((uint32_t)HuffTableDC0->HuffVal[index - 1UL] & 0xFFUL) << 24) |
+ (((uint32_t)HuffTableDC0->HuffVal[index - 2UL] & 0xFFUL) << 16) |
+ (((uint32_t)HuffTableDC0->HuffVal[index - 3UL] & 0xFFUL) << 8) |
+ ((uint32_t)HuffTableDC0->HuffVal[index - 4UL] & 0xFFUL);
+ address--;
+ index -= 4UL;
+ }
+
+ /* AC0 Huffman Table : BITS*/
+ /* AC0 BITS is a 16 Bytes table i.e 4x32bits words from DHTMEM base address + 7 to DHTMEM + 10*/
+ address = (hjpeg->Instance->DHTMEM + 10UL);
+ index = 16;
+ while (index > 3UL)
+ {
+
+ *address = (((uint32_t)HuffTableAC0->Bits[index - 1UL] & 0xFFUL) << 24) |
+ (((uint32_t)HuffTableAC0->Bits[index - 2UL] & 0xFFUL) << 16) |
+ (((uint32_t)HuffTableAC0->Bits[index - 3UL] & 0xFFUL) << 8) |
+ ((uint32_t)HuffTableAC0->Bits[index - 4UL] & 0xFFUL);
+ address--;
+ index -= 4UL;
+
+ }
+ /* AC0 Huffman Table : Val*/
+ /* AC0 VALS is a 162 Bytes table i.e 41x32bits words from DHTMEM base address + 11 to DHTMEM + 51 */
+ /* only Byte 0 and Byte 1 of the last word (@ DHTMEM + 51) belong to AC0 VALS table */
+ address = (hjpeg->Instance->DHTMEM + 51);
+ value = *address & 0xFFFF0000U;
+ value = value | (((uint32_t)HuffTableAC0->HuffVal[161] & 0xFFUL) << 8) | ((uint32_t)HuffTableAC0->HuffVal[160] & 0xFFUL);
+ *address = value;
+
+ /*continue setting 160 AC0 huffman values */
+ address--; /* address = hjpeg->Instance->DHTMEM + 50*/
+ index = 160;
+ while (index > 3UL)
+ {
+ *address = (((uint32_t)HuffTableAC0->HuffVal[index - 1UL] & 0xFFUL) << 24) |
+ (((uint32_t)HuffTableAC0->HuffVal[index - 2UL] & 0xFFUL) << 16) |
+ (((uint32_t)HuffTableAC0->HuffVal[index - 3UL] & 0xFFUL) << 8) |
+ ((uint32_t)HuffTableAC0->HuffVal[index - 4UL] & 0xFFUL);
+ address--;
+ index -= 4UL;
+ }
+
+ /* DC1 Huffman Table : BITS*/
+ /* DC1 BITS is a 16 Bytes table i.e 4x32bits words from DHTMEM + 51 base address to DHTMEM + 55*/
+ /* only Byte 2 and Byte 3 of the first word (@ DHTMEM + 51) belong to DC1 Bits table */
+ address = (hjpeg->Instance->DHTMEM + 51);
+ value = *address & 0x0000FFFFU;
+ value = value | (((uint32_t)HuffTableDC1->Bits[1] & 0xFFUL) << 24) | (((uint32_t)HuffTableDC1->Bits[0] & 0xFFUL) << 16);
+ *address = value;
+
+ /* only Byte 0 and Byte 1 of the last word (@ DHTMEM + 55) belong to DC1 Bits table */
+ address = (hjpeg->Instance->DHTMEM + 55);
+ value = *address & 0xFFFF0000U;
+ value = value | (((uint32_t)HuffTableDC1->Bits[15] & 0xFFUL) << 8) | ((uint32_t)HuffTableDC1->Bits[14] & 0xFFUL);
+ *address = value;
+
+ /*continue setting 12 DC1 huffman Bits from DHTMEM + 54 down to DHTMEM + 52*/
+ address--;
+ index = 12;
+ while (index > 3UL)
+ {
+
+ *address = (((uint32_t)HuffTableDC1->Bits[index + 1UL] & 0xFFUL) << 24) |
+ (((uint32_t)HuffTableDC1->Bits[index] & 0xFFUL) << 16) |
+ (((uint32_t)HuffTableDC1->Bits[index - 1UL] & 0xFFUL) << 8) |
+ ((uint32_t)HuffTableDC1->Bits[index - 2UL] & 0xFFUL);
+ address--;
+ index -= 4UL;
+
+ }
+ /* DC1 Huffman Table : Val*/
+ /* DC1 VALS is a 12 Bytes table i.e 3x32bits words from DHTMEM base address +55 to DHTMEM + 58 */
+ /* only Byte 2 and Byte 3 of the first word (@ DHTMEM + 55) belong to DC1 Val table */
+ address = (hjpeg->Instance->DHTMEM + 55);
+ value = *address & 0x0000FFFFUL;
+ value = value | (((uint32_t)HuffTableDC1->HuffVal[1] & 0xFFUL) << 24) | (((uint32_t)HuffTableDC1->HuffVal[0] & 0xFFUL) <<
+ 16);
+ *address = value;
+
+ /* only Byte 0 and Byte 1 of the last word (@ DHTMEM + 58) belong to DC1 Val table */
+ address = (hjpeg->Instance->DHTMEM + 58);
+ value = *address & 0xFFFF0000UL;
+ value = value | (((uint32_t)HuffTableDC1->HuffVal[11] & 0xFFUL) << 8) | ((uint32_t)HuffTableDC1->HuffVal[10] & 0xFFUL);
+ *address = value;
+
+ /*continue setting 8 DC1 huffman val from DHTMEM + 57 down to DHTMEM + 56*/
+ address--;
+ index = 8;
+ while (index > 3UL)
+ {
+ *address = (((uint32_t)HuffTableDC1->HuffVal[index + 1UL] & 0xFFUL) << 24) |
+ (((uint32_t)HuffTableDC1->HuffVal[index] & 0xFFUL) << 16) |
+ (((uint32_t)HuffTableDC1->HuffVal[index - 1UL] & 0xFFUL) << 8) |
+ ((uint32_t)HuffTableDC1->HuffVal[index - 2UL] & 0xFFUL);
+ address--;
+ index -= 4UL;
+ }
+
+ /* AC1 Huffman Table : BITS*/
+ /* AC1 BITS is a 16 Bytes table i.e 4x32bits words from DHTMEM base address + 58 to DHTMEM + 62*/
+ /* only Byte 2 and Byte 3 of the first word (@ DHTMEM + 58) belong to AC1 Bits table */
+ address = (hjpeg->Instance->DHTMEM + 58);
+ value = *address & 0x0000FFFFU;
+ value = value | (((uint32_t)HuffTableAC1->Bits[1] & 0xFFUL) << 24) | (((uint32_t)HuffTableAC1->Bits[0] & 0xFFUL) << 16);
+ *address = value;
+
+ /* only Byte 0 and Byte 1 of the last word (@ DHTMEM + 62) belong to Bits Val table */
+ address = (hjpeg->Instance->DHTMEM + 62);
+ value = *address & 0xFFFF0000U;
+ value = value | (((uint32_t)HuffTableAC1->Bits[15] & 0xFFUL) << 8) | ((uint32_t)HuffTableAC1->Bits[14] & 0xFFUL);
+ *address = value;
+
+ /*continue setting 12 AC1 huffman Bits from DHTMEM + 61 down to DHTMEM + 59*/
+ address--;
+ index = 12;
+ while (index > 3UL)
+ {
+
+ *address = (((uint32_t)HuffTableAC1->Bits[index + 1UL] & 0xFFUL) << 24) |
+ (((uint32_t)HuffTableAC1->Bits[index] & 0xFFUL) << 16) |
+ (((uint32_t)HuffTableAC1->Bits[index - 1UL] & 0xFFUL) << 8) |
+ ((uint32_t)HuffTableAC1->Bits[index - 2UL] & 0xFFUL);
+ address--;
+ index -= 4UL;
+
+ }
+ /* AC1 Huffman Table : Val*/
+ /* AC1 VALS is a 162 Bytes table i.e 41x32bits words from DHTMEM base address + 62 to DHTMEM + 102 */
+ /* only Byte 2 and Byte 3 of the first word (@ DHTMEM + 62) belong to AC1 VALS table */
+ address = (hjpeg->Instance->DHTMEM + 62);
+ value = *address & 0x0000FFFFUL;
+ value = value | (((uint32_t)HuffTableAC1->HuffVal[1] & 0xFFUL) << 24) | (((uint32_t)HuffTableAC1->HuffVal[0] & 0xFFUL) <<
+ 16);
+ *address = value;
+
+ /*continue setting 160 AC1 huffman values from DHTMEM + 63 to DHTMEM+102 */
+ address = (hjpeg->Instance->DHTMEM + 102);
+ index = 160;
+ while (index > 3UL)
+ {
+ *address = (((uint32_t)HuffTableAC1->HuffVal[index + 1UL] & 0xFFUL) << 24) |
+ (((uint32_t)HuffTableAC1->HuffVal[index] & 0xFFUL) << 16) |
+ (((uint32_t)HuffTableAC1->HuffVal[index - 1UL] & 0xFFUL) << 8) |
+ ((uint32_t)HuffTableAC1->HuffVal[index - 2UL] & 0xFFUL);
+ address--;
+ index -= 4UL;
+ }
+
+}
+
+/**
+ * @brief Configure the JPEG registers with a given quantization table
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param QTable pointer to an array of 64 bytes giving the quantization table
+ * @param QTableAddress destination quantization address in the JPEG peripheral
+ * it could be QMEM0, QMEM1, QMEM2 or QMEM3
+ * @retval 0 if no error, 1 if error
+ */
+static uint32_t JPEG_Set_Quantization_Mem(JPEG_HandleTypeDef *hjpeg, uint8_t *QTable,
+ __IO uint32_t *QTableAddress)
+{
+ uint32_t i;
+ uint32_t j;
+ uint32_t quantRow;
+ uint32_t quantVal;
+ uint32_t ScaleFactor;
+ __IO uint32_t *tableAddress;
+
+ tableAddress = QTableAddress;
+
+ if ((hjpeg->Conf.ImageQuality >= 50UL) && (hjpeg->Conf.ImageQuality <= 100UL))
+ {
+ ScaleFactor = 200UL - (hjpeg->Conf.ImageQuality * 2UL);
+ }
+ else if (hjpeg->Conf.ImageQuality > 0UL)
+ {
+ ScaleFactor = ((uint32_t) 5000) / ((uint32_t) hjpeg->Conf.ImageQuality);
+ }
+ else
+ {
+ return 1UL;
+ }
+
+ /*Quantization_table = (Standard_quanization_table * ScaleFactor + 50) / 100*/
+ i = 0;
+ while (i < (JPEG_QUANT_TABLE_SIZE - 3UL))
+ {
+ quantRow = 0;
+ for (j = 0; j < 4UL; j++)
+ {
+ /* Note that the quantization coefficients must be specified in the table in zigzag order */
+ quantVal = ((((uint32_t) QTable[JPEG_ZIGZAG_ORDER[i + j]]) * ScaleFactor) + 50UL) / 100UL;
+
+ if (quantVal == 0UL)
+ {
+ quantVal = 1UL;
+ }
+ else if (quantVal > 255UL)
+ {
+ quantVal = 255UL;
+ }
+ else
+ {
+ /* Nothing to do, keep same value of quantVal */
+ }
+
+ quantRow |= ((quantVal & 0xFFUL) << (8UL * j));
+ }
+
+ i += 4UL;
+ *tableAddress = quantRow;
+ tableAddress ++;
+ }
+
+ /* Return function status */
+ return 0UL;
+}
+
+/**
+ * @brief Configure the JPEG registers for YCbCr color space
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+static void JPEG_SetColorYCBCR(JPEG_HandleTypeDef *hjpeg)
+{
+ uint32_t ySamplingH;
+ uint32_t ySamplingV;
+ uint32_t yblockNb;
+
+ /*Set Number of color components to 3*/
+ hjpeg->Instance->CONFR1 &= ~JPEG_CONFR1_NF;
+ hjpeg->Instance->CONFR1 |= JPEG_CONFR1_NF_1;
+
+ /* compute MCU block size and Y, Cb ,Cr sampling factors*/
+ if (hjpeg->Conf.ChromaSubsampling == JPEG_420_SUBSAMPLING)
+ {
+ ySamplingH = JPEG_CONFR4_HSF_1; /* Hs = 2*/
+ ySamplingV = JPEG_CONFR4_VSF_1; /* Vs = 2*/
+
+ yblockNb = 0x30; /* 4 blocks of 8x8*/
+ }
+ else if (hjpeg->Conf.ChromaSubsampling == JPEG_422_SUBSAMPLING)
+ {
+ ySamplingH = JPEG_CONFR4_HSF_1; /* Hs = 2*/
+ ySamplingV = JPEG_CONFR4_VSF_0; /* Vs = 1*/
+
+ yblockNb = 0x10; /* 2 blocks of 8x8*/
+ }
+ else /*JPEG_444_SUBSAMPLING and default*/
+ {
+ ySamplingH = JPEG_CONFR4_HSF_0; /* Hs = 1*/
+ ySamplingV = JPEG_CONFR4_VSF_0; /* Vs = 1*/
+
+ yblockNb = 0; /* 1 block of 8x8*/
+ }
+
+ hjpeg->Instance->CONFR1 &= ~(JPEG_CONFR1_NF | JPEG_CONFR1_NS);
+ hjpeg->Instance->CONFR1 |= (JPEG_CONFR1_NF_1 | JPEG_CONFR1_NS_1);
+
+ /*Reset CONFR4 register*/
+ hjpeg->Instance->CONFR4 = 0;
+ /*Set Horizental and Vertical sampling factor , number of blocks , Quantization table and Huffman AC/DC tables for component 0*/
+ hjpeg->Instance->CONFR4 |= (ySamplingH | ySamplingV | (yblockNb & JPEG_CONFR4_NB));
+
+ /*Reset CONFR5 register*/
+ hjpeg->Instance->CONFR5 = 0;
+ /*Set Horizental and Vertical sampling factor , number of blocks , Quantization table and Huffman AC/DC tables for component 1*/
+ hjpeg->Instance->CONFR5 |= (JPEG_CONFR5_HSF_0 | JPEG_CONFR5_VSF_0 | JPEG_CONFR5_QT_0 | JPEG_CONFR5_HA | JPEG_CONFR5_HD);
+
+ /*Reset CONFR6 register*/
+ hjpeg->Instance->CONFR6 = 0;
+ /*Set Horizental and Vertical sampling factor and number of blocks for component 2*/
+ /* In YCBCR , by default, both chrominance components (component 1 and component 2) use the same Quantization table (table 1) */
+ /* In YCBCR , both chrominance components (component 1 and component 2) use the same Huffman tables (table 1) */
+ hjpeg->Instance->CONFR6 |= (JPEG_CONFR6_HSF_0 | JPEG_CONFR6_VSF_0 | JPEG_CONFR6_QT_0 | JPEG_CONFR6_HA | JPEG_CONFR6_HD);
+
+}
+
+/**
+ * @brief Configure the JPEG registers for GrayScale color space
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+static void JPEG_SetColorGrayScale(JPEG_HandleTypeDef *hjpeg)
+{
+ /*Set Number of color components to 1*/
+ hjpeg->Instance->CONFR1 &= ~(JPEG_CONFR1_NF | JPEG_CONFR1_NS);
+
+ /*in GrayScale use 1 single Quantization table (Table 0)*/
+ /*in GrayScale use only one couple of AC/DC huffman table (table 0)*/
+
+ /*Reset CONFR4 register*/
+ hjpeg->Instance->CONFR4 = 0;
+ /*Set Horizental and Vertical sampling factor , number of blocks , Quantization table and Huffman AC/DC tables for component 0*/
+ hjpeg->Instance->CONFR4 |= JPEG_CONFR4_HSF_0 | JPEG_CONFR4_VSF_0 ;
+}
+
+/**
+ * @brief Configure the JPEG registers for CMYK color space
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+static void JPEG_SetColorCMYK(JPEG_HandleTypeDef *hjpeg)
+{
+ uint32_t ySamplingH;
+ uint32_t ySamplingV;
+ uint32_t yblockNb;
+
+ /*Set Number of color components to 4*/
+ hjpeg->Instance->CONFR1 |= (JPEG_CONFR1_NF | JPEG_CONFR1_NS);
+
+ /* compute MCU block size and Y, Cb ,Cr sampling factors*/
+ if (hjpeg->Conf.ChromaSubsampling == JPEG_420_SUBSAMPLING)
+ {
+ ySamplingH = JPEG_CONFR4_HSF_1; /* Hs = 2*/
+ ySamplingV = JPEG_CONFR4_VSF_1; /* Vs = 2*/
+
+ yblockNb = 0x30; /* 4 blocks of 8x8*/
+ }
+ else if (hjpeg->Conf.ChromaSubsampling == JPEG_422_SUBSAMPLING)
+ {
+ ySamplingH = JPEG_CONFR4_HSF_1; /* Hs = 2*/
+ ySamplingV = JPEG_CONFR4_VSF_0; /* Vs = 1*/
+
+ yblockNb = 0x10; /* 2 blocks of 8x8*/
+ }
+ else /*JPEG_444_SUBSAMPLING and default*/
+ {
+ ySamplingH = JPEG_CONFR4_HSF_0; /* Hs = 1*/
+ ySamplingV = JPEG_CONFR4_VSF_0; /* Vs = 1*/
+
+ yblockNb = 0; /* 1 block of 8x8*/
+ }
+
+ /*Reset CONFR4 register*/
+ hjpeg->Instance->CONFR4 = 0;
+ /*Set Horizental and Vertical sampling factor , number of blocks , Quantization table and Huffman AC/DC tables for component 0*/
+ hjpeg->Instance->CONFR4 |= (ySamplingH | ySamplingV | (yblockNb & JPEG_CONFR4_NB));
+
+ /*Reset CONFR5 register*/
+ hjpeg->Instance->CONFR5 = 0;
+ /*Set Horizental and Vertical sampling factor , number of blocks , Quantization table and Huffman AC/DC tables for component 1*/
+ hjpeg->Instance->CONFR5 |= (JPEG_CONFR5_HSF_0 | JPEG_CONFR5_VSF_0);
+
+ /*Reset CONFR6 register*/
+ hjpeg->Instance->CONFR6 = 0;
+ /*Set Horizental and Vertical sampling factor , number of blocks , Quantization table and Huffman AC/DC tables for component 2*/
+ hjpeg->Instance->CONFR6 |= (JPEG_CONFR6_HSF_0 | JPEG_CONFR6_VSF_0);
+
+ /*Reset CONFR7 register*/
+ hjpeg->Instance->CONFR7 = 0;
+ /*Set Horizental and Vertical sampling factor , number of blocks , Quantization table and Huffman AC/DC tables for component 3*/
+ hjpeg->Instance->CONFR7 |= (JPEG_CONFR7_HSF_0 | JPEG_CONFR7_VSF_0);
+}
+
+/**
+ * @brief Init the JPEG encoding/decoding process in case of Polling or Interrupt and DMA
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None
+ */
+static void JPEG_Init_Process(JPEG_HandleTypeDef *hjpeg)
+{
+ /*Reset pause*/
+ hjpeg->Context &= (~(JPEG_CONTEXT_PAUSE_INPUT | JPEG_CONTEXT_PAUSE_OUTPUT));
+
+ if ((hjpeg->Context & JPEG_CONTEXT_OPERATION_MASK) == JPEG_CONTEXT_DECODE)
+ {
+ /*Set JPEG Codec to Decoding mode */
+ hjpeg->Instance->CONFR1 |= JPEG_CONFR1_DE;
+ }
+ else /* JPEG_CONTEXT_ENCODE */
+ {
+ /*Set JPEG Codec to Encoding mode */
+ hjpeg->Instance->CONFR1 &= ~JPEG_CONFR1_DE;
+ }
+
+ /*Stop JPEG processing */
+ hjpeg->Instance->CONFR0 &= ~JPEG_CONFR0_START;
+
+ /* Disable All Interrupts */
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_INTERRUPT_MASK);
+
+ /* Flush input and output FIFOs*/
+ hjpeg->Instance->CR |= JPEG_CR_IFF;
+ hjpeg->Instance->CR |= JPEG_CR_OFF;
+
+ /* Clear all flags */
+ __HAL_JPEG_CLEAR_FLAG(hjpeg, JPEG_FLAG_ALL);
+
+ /*Start Encoding/Decoding*/
+ hjpeg->Instance->CONFR0 |= JPEG_CONFR0_START;
+
+ if ((hjpeg->Context & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_IT)
+ {
+ /*Enable IN/OUT, end of Conversation, and end of header parsing interruptions*/
+ __HAL_JPEG_ENABLE_IT(hjpeg, JPEG_IT_IFT | JPEG_IT_IFNF | JPEG_IT_OFT | JPEG_IT_OFNE | JPEG_IT_EOC | JPEG_IT_HPD);
+ }
+ else if ((hjpeg->Context & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_DMA)
+ {
+ /*Enable End Of Conversation, and End Of Header parsing interruptions*/
+ __HAL_JPEG_ENABLE_IT(hjpeg, JPEG_IT_EOC | JPEG_IT_HPD);
+
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief JPEG encoding/decoding process in case of Polling or Interrupt
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval JPEG_PROCESS_DONE if the process has ends else JPEG_PROCESS_ONGOING
+ */
+static uint32_t JPEG_Process(JPEG_HandleTypeDef *hjpeg)
+{
+ uint32_t tmpContext;
+
+ /*End of header processing flag rised*/
+ if ((hjpeg->Context & JPEG_CONTEXT_OPERATION_MASK) == JPEG_CONTEXT_DECODE)
+ {
+ if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_HPDF) != 0UL)
+ {
+ /*Call Header parsing complet callback */
+ (void) HAL_JPEG_GetInfo(hjpeg, &hjpeg->Conf);
+ /* Reset the ImageQuality */
+ hjpeg->Conf.ImageQuality = 0;
+ /* Note : the image quality is only available at the end of the decoding operation */
+ /* at the current stage the calculated image quality is not correct so reset it */
+
+ /*Call Info Ready callback */
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->InfoReadyCallback(hjpeg, &hjpeg->Conf);
+#else
+ HAL_JPEG_InfoReadyCallback(hjpeg, &hjpeg->Conf);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_IT_HPD);
+
+ /* Clear header processing done flag */
+ __HAL_JPEG_CLEAR_FLAG(hjpeg, JPEG_FLAG_HPDF);
+ }
+ }
+
+ /*Input FIFO status handling*/
+ if ((hjpeg->Context & JPEG_CONTEXT_PAUSE_INPUT) == 0UL)
+ {
+ if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_IFTF) != 0UL)
+ {
+ /*Input FIFO threshold flag rised*/
+ /*JPEG_FIFO_TH_SIZE words can be written in */
+ JPEG_ReadInputData(hjpeg, JPEG_FIFO_TH_SIZE);
+ }
+ else if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_IFNFF) != 0UL)
+ {
+ /*Input FIFO Not Full flag rised*/
+ /*32-bit value can be written in */
+ JPEG_ReadInputData(hjpeg, 1);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+
+
+ /*Output FIFO flag handling*/
+ if ((hjpeg->Context & JPEG_CONTEXT_PAUSE_OUTPUT) == 0UL)
+ {
+ if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_OFTF) != 0UL)
+ {
+ /*Output FIFO threshold flag rised*/
+ /*JPEG_FIFO_TH_SIZE words can be read out */
+ JPEG_StoreOutputData(hjpeg, JPEG_FIFO_TH_SIZE);
+ }
+ else if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_OFNEF) != 0UL)
+ {
+ /*Output FIFO Not Empty flag rised*/
+ /*32-bit value can be read out */
+ JPEG_StoreOutputData(hjpeg, 1);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+
+ /*End of Conversion handling :i.e EOC flag is high and OFTF low and OFNEF low*/
+ if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_EOCF | JPEG_FLAG_OFTF | JPEG_FLAG_OFNEF) == JPEG_FLAG_EOCF)
+ {
+ /*Stop Encoding/Decoding*/
+ hjpeg->Instance->CONFR0 &= ~JPEG_CONFR0_START;
+
+ if ((hjpeg->Context & JPEG_CONTEXT_METHOD_MASK) == JPEG_CONTEXT_IT)
+ {
+ /* Disable All Interrupts */
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_INTERRUPT_MASK);
+ }
+
+ /* Clear all flags */
+ __HAL_JPEG_CLEAR_FLAG(hjpeg, JPEG_FLAG_ALL);
+
+ /*Call End of conversion callback */
+ if (hjpeg->JpegOutCount > 0UL)
+ {
+ /*Output Buffer is not empty, call DecodedDataReadyCallback*/
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#else
+ HAL_JPEG_DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ hjpeg->JpegOutCount = 0;
+ }
+
+ /*Reset Context Operation*/
+ tmpContext = hjpeg->Context;
+ /*Clear all context fields execpt JPEG_CONTEXT_CONF_ENCODING and JPEG_CONTEXT_CUSTOM_TABLES*/
+ hjpeg->Context &= (JPEG_CONTEXT_CONF_ENCODING | JPEG_CONTEXT_CUSTOM_TABLES);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ /*Call End of Encoding/Decoding callback */
+ if ((tmpContext & JPEG_CONTEXT_OPERATION_MASK) == JPEG_CONTEXT_DECODE)
+ {
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DecodeCpltCallback(hjpeg);
+#else
+ HAL_JPEG_DecodeCpltCallback(hjpeg);
+#endif /*USE_HAL_JPEG_REGISTER_CALLBACKS*/
+ }
+ else /* JPEG_CONTEXT_ENCODE */
+ {
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->EncodeCpltCallback(hjpeg);
+#else
+ HAL_JPEG_EncodeCpltCallback(hjpeg);
+#endif
+ }
+
+ return JPEG_PROCESS_DONE;
+ }
+
+
+ return JPEG_PROCESS_ONGOING;
+}
+
+/**
+ * @brief Store some output data from the JPEG peripheral to the output buffer.
+ * This function is used when the JPEG peripheral has new data to output
+ * in case of Polling or Interrupt process
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param nbOutputWords Number of output words (of 32 bits) ready from the JPEG peripheral
+ * @retval None
+ */
+static void JPEG_StoreOutputData(JPEG_HandleTypeDef *hjpeg, uint32_t nbOutputWords)
+{
+ uint32_t index;
+ uint32_t nb_words;
+ uint32_t nb_bytes;
+ uint32_t dataword;
+
+ if (hjpeg->OutDataLength >= (hjpeg->JpegOutCount + (nbOutputWords * 4UL)))
+ {
+ for (index = 0; index < nbOutputWords; index++)
+ {
+ /*Transfer 32 bits from the JPEG output FIFO*/
+ dataword = hjpeg->Instance->DOR;
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount] = (uint8_t)(dataword & 0x000000FFUL);
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount + 1UL] = (uint8_t)((dataword & 0x0000FF00UL) >> 8);
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount + 2UL] = (uint8_t)((dataword & 0x00FF0000UL) >> 16);
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount + 3UL] = (uint8_t)((dataword & 0xFF000000UL) >> 24);
+ hjpeg->JpegOutCount += 4UL;
+ }
+ if (hjpeg->OutDataLength == hjpeg->JpegOutCount)
+ {
+ /*Output Buffer is full, call DecodedDataReadyCallback*/
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#else
+ HAL_JPEG_DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#endif /*USE_HAL_JPEG_REGISTER_CALLBACKS*/
+ hjpeg->JpegOutCount = 0;
+ }
+ }
+ else if (hjpeg->OutDataLength > hjpeg->JpegOutCount)
+ {
+ nb_words = (hjpeg->OutDataLength - hjpeg->JpegOutCount) / 4UL;
+ for (index = 0; index < nb_words; index++)
+ {
+ /*Transfer 32 bits from the JPEG output FIFO*/
+ dataword = hjpeg->Instance->DOR;
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount] = (uint8_t)(dataword & 0x000000FFUL);
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount + 1UL] = (uint8_t)((dataword & 0x0000FF00UL) >> 8);
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount + 2UL] = (uint8_t)((dataword & 0x00FF0000UL) >> 16);
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount + 3UL] = (uint8_t)((dataword & 0xFF000000UL) >> 24);
+ hjpeg->JpegOutCount += 4UL;
+ }
+ if (hjpeg->OutDataLength == hjpeg->JpegOutCount)
+ {
+ /*Output Buffer is full, call DecodedDataReadyCallback*/
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#else
+ HAL_JPEG_DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+ hjpeg->JpegOutCount = 0;
+ }
+ else
+ {
+ nb_bytes = hjpeg->OutDataLength - hjpeg->JpegOutCount;
+ dataword = hjpeg->Instance->DOR;
+ for (index = 0; index < nb_bytes; index++)
+ {
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount] = (uint8_t)((dataword >> (8UL * (index & 0x3UL))) & 0xFFUL);
+ hjpeg->JpegOutCount++;
+ }
+ /*Output Buffer is full, call DecodedDataReadyCallback*/
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#else
+ HAL_JPEG_DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ hjpeg->JpegOutCount = 0;
+
+ nb_bytes = 4UL - nb_bytes;
+ for (index = nb_bytes; index < 4UL; index++)
+ {
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount] = (uint8_t)((dataword >> (8UL * index)) & 0xFFUL);
+ hjpeg->JpegOutCount++;
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief Read some input Data from the input buffer.
+ * This function is used when the JPEG peripheral needs new data
+ * in case of Polling or Interrupt process
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @param nbRequestWords Number of input words (of 32 bits) that the JPE peripheral request
+ * @retval None
+ */
+static void JPEG_ReadInputData(JPEG_HandleTypeDef *hjpeg, uint32_t nbRequestWords)
+{
+ uint32_t nb_bytes = 0;
+ uint32_t nb_words;
+ uint32_t index;
+ uint32_t dataword;
+ uint32_t input_count;
+
+ if ((hjpeg->InDataLength == 0UL) || (nbRequestWords == 0UL))
+ {
+ /* No more Input data : nothing to do*/
+ (void) HAL_JPEG_Pause(hjpeg, JPEG_PAUSE_RESUME_INPUT);
+ }
+ else if (hjpeg->InDataLength > hjpeg->JpegInCount)
+ {
+ nb_bytes = hjpeg->InDataLength - hjpeg->JpegInCount;
+ }
+ else if (hjpeg->InDataLength == hjpeg->JpegInCount)
+ {
+ /*Call HAL_JPEG_GetDataCallback to get new data */
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->GetDataCallback(hjpeg, hjpeg->JpegInCount);
+#else
+ HAL_JPEG_GetDataCallback(hjpeg, hjpeg->JpegInCount);
+#endif /*USE_HAL_JPEG_REGISTER_CALLBACKS*/
+
+ if (hjpeg->InDataLength > 4UL)
+ {
+ hjpeg->InDataLength = hjpeg->InDataLength - (hjpeg->InDataLength % 4UL);
+ }
+ hjpeg->JpegInCount = 0;
+ nb_bytes = hjpeg->InDataLength;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ if (((hjpeg->Context & JPEG_CONTEXT_PAUSE_INPUT) == 0UL) && (nb_bytes > 0UL))
+ {
+ nb_words = nb_bytes / 4UL;
+ if (nb_words >= nbRequestWords)
+ {
+ for (index = 0; index < nbRequestWords; index++)
+ {
+ input_count = hjpeg->JpegInCount;
+ hjpeg->Instance->DIR = (((uint32_t)(hjpeg->pJpegInBuffPtr[input_count])) | \
+ (((uint32_t)(hjpeg->pJpegInBuffPtr[input_count + 1UL])) << 8) | \
+ (((uint32_t)(hjpeg->pJpegInBuffPtr[input_count + 2UL])) << 16) | \
+ (((uint32_t)(hjpeg->pJpegInBuffPtr[input_count + 3UL])) << 24));
+
+ hjpeg->JpegInCount += 4UL;
+ }
+ }
+ else /*nb_words < nbRequestWords*/
+ {
+ if (nb_words > 0UL)
+ {
+ for (index = 0; index < nb_words; index++)
+ {
+ input_count = hjpeg->JpegInCount;
+ hjpeg->Instance->DIR = (((uint32_t)(hjpeg->pJpegInBuffPtr[input_count])) | \
+ (((uint32_t)(hjpeg->pJpegInBuffPtr[input_count + 1UL])) << 8) | \
+ (((uint32_t)(hjpeg->pJpegInBuffPtr[input_count + 2UL])) << 16) | \
+ (((uint32_t)(hjpeg->pJpegInBuffPtr[input_count + 3UL])) << 24));
+
+ hjpeg->JpegInCount += 4UL;
+ }
+ }
+ else
+ {
+ /* end of file*/
+ dataword = 0;
+ for (index = 0; index < nb_bytes; index++)
+ {
+ dataword |= (uint32_t)hjpeg->pJpegInBuffPtr[hjpeg->JpegInCount] << (8UL * (index & 0x03UL));
+ hjpeg->JpegInCount++;
+ }
+ hjpeg->Instance->DIR = dataword;
+ }
+ }
+ }
+}
+
+/**
+ * @brief Start the JPEG DMA process (encoding/decoding)
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval JPEG_PROCESS_DONE if process ends else JPEG_PROCESS_ONGOING
+ */
+static HAL_StatusTypeDef JPEG_DMA_StartProcess(JPEG_HandleTypeDef *hjpeg)
+{
+ uint32_t inXfrSize, outXfrSize;
+
+ /*if the MDMA In is triggred with JPEG In FIFO Threshold flag
+ then MDMA In buffer size is 32 bytes
+ else (MDMA In is triggred with JPEG In FIFO not full flag)
+ then MDMA In buffer size is 4 bytes
+ */
+ inXfrSize = hjpeg->hdmain->Init.BufferTransferLength;
+
+ /*if the MDMA Out is triggred with JPEG Out FIFO Threshold flag
+ then MDMA out buffer size is 32 bytes
+ else (MDMA Out is triggred with JPEG Out FIFO not empty flag)
+ then MDMA buffer size is 4 bytes
+ */
+ outXfrSize = hjpeg->hdmaout->Init.BufferTransferLength;
+
+ if ((hjpeg->InDataLength < inXfrSize) || (hjpeg->OutDataLength < outXfrSize))
+ {
+ return HAL_ERROR;
+ }
+ /* Set the JPEG MDMA In transfer complete callback */
+ hjpeg->hdmain->XferCpltCallback = JPEG_MDMAInCpltCallback;
+ /* Set the MDMA In error callback */
+ hjpeg->hdmain->XferErrorCallback = JPEG_MDMAErrorCallback;
+
+ /* Set the JPEG MDMA Out transfer complete callback */
+ hjpeg->hdmaout->XferCpltCallback = JPEG_MDMAOutCpltCallback;
+ /* Set the MDMA In error callback */
+ hjpeg->hdmaout->XferErrorCallback = JPEG_MDMAErrorCallback;
+ /* Set the MDMA Out Abort callback */
+ hjpeg->hdmaout->XferAbortCallback = JPEG_MDMAOutAbortCallback;
+
+ if ((inXfrSize == 0UL) || (outXfrSize == 0UL))
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ return HAL_ERROR;
+ }
+ /*MDMA transfer size (BNDTR) must be a multiple of MDMA buffer size (TLEN)*/
+ hjpeg->InDataLength = hjpeg->InDataLength - (hjpeg->InDataLength % inXfrSize);
+
+ /*MDMA transfer size (BNDTR) must be a multiple of MDMA buffer size (TLEN)*/
+ hjpeg->OutDataLength = hjpeg->OutDataLength - (hjpeg->OutDataLength % outXfrSize);
+
+
+ /* Start MDMA FIFO Out transfer */
+ if (HAL_MDMA_Start_IT(hjpeg->hdmaout, (uint32_t)&hjpeg->Instance->DOR, (uint32_t)hjpeg->pJpegOutBuffPtr,
+ hjpeg->OutDataLength, 1) != HAL_OK)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ return HAL_ERROR;
+ }
+ /* Start DMA FIFO In transfer */
+ if (HAL_MDMA_Start_IT(hjpeg->hdmain, (uint32_t)hjpeg->pJpegInBuffPtr, (uint32_t)&hjpeg->Instance->DIR,
+ hjpeg->InDataLength, 1) != HAL_OK)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Continue the current JPEG DMA process (encoding/decoding)
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval JPEG_PROCESS_DONE if process ends else JPEG_PROCESS_ONGOING
+ */
+static void JPEG_DMA_ContinueProcess(JPEG_HandleTypeDef *hjpeg)
+{
+ /*End of header processing flag rises*/
+ if ((hjpeg->Context & JPEG_CONTEXT_OPERATION_MASK) == JPEG_CONTEXT_DECODE)
+ {
+ if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_HPDF) != 0UL)
+ {
+ /*Call Header parsing complete callback */
+ (void) HAL_JPEG_GetInfo(hjpeg, &hjpeg->Conf);
+
+ /* Reset the ImageQuality */
+ hjpeg->Conf.ImageQuality = 0;
+ /* Note : the image quality is only available at the end of the decoding operation */
+ /* at the current stage the calculated image quality is not correct so reset it */
+
+ /*Call Info Ready callback */
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->InfoReadyCallback(hjpeg, &hjpeg->Conf);
+#else
+ HAL_JPEG_InfoReadyCallback(hjpeg, &hjpeg->Conf);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_IT_HPD);
+
+ /* Clear header processing done flag */
+ __HAL_JPEG_CLEAR_FLAG(hjpeg, JPEG_FLAG_HPDF);
+ }
+ }
+
+ /*End of Conversion handling*/
+ if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_EOCF) != 0UL)
+ {
+
+ hjpeg->Context |= JPEG_CONTEXT_ENDING_DMA;
+
+ /*Stop Encoding/Decoding*/
+ hjpeg->Instance->CONFR0 &= ~JPEG_CONFR0_START;
+
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_INTERRUPT_MASK);
+
+ /* Clear all flags */
+ __HAL_JPEG_CLEAR_FLAG(hjpeg, JPEG_FLAG_ALL);
+
+ if (hjpeg->hdmain->State == HAL_MDMA_STATE_BUSY)
+ {
+ /* Stop the MDMA In Xfer*/
+ (void) HAL_MDMA_Abort_IT(hjpeg->hdmain);
+ }
+
+ if (hjpeg->hdmaout->State == HAL_MDMA_STATE_BUSY)
+ {
+ /* Stop the MDMA out Xfer*/
+ (void) HAL_MDMA_Abort_IT(hjpeg->hdmaout);
+ }
+ else
+ {
+ JPEG_DMA_EndProcess(hjpeg);
+ }
+ }
+
+
+}
+
+/**
+ * @brief Finalize the current JPEG DMA process (encoding/decoding)
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval JPEG_PROCESS_DONE
+ */
+static void JPEG_DMA_EndProcess(JPEG_HandleTypeDef *hjpeg)
+{
+ uint32_t tmpContext;
+ hjpeg->JpegOutCount = hjpeg->OutDataLength - (hjpeg->hdmaout->Instance->CBNDTR & MDMA_CBNDTR_BNDT);
+
+ /*if Output Buffer is full, call HAL_JPEG_DataReadyCallback*/
+ if (hjpeg->JpegOutCount == hjpeg->OutDataLength)
+ {
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#else
+ HAL_JPEG_DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ hjpeg->JpegOutCount = 0;
+ }
+
+ /*Check if remaining data in the output FIFO*/
+ if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_OFNEF) == 0UL)
+ {
+ if (hjpeg->JpegOutCount > 0UL)
+ {
+ /*Output Buffer is not empty, call DecodedDataReadyCallback*/
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#else
+ HAL_JPEG_DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ hjpeg->JpegOutCount = 0;
+ }
+
+ /*Stop Encoding/Decoding*/
+ hjpeg->Instance->CONFR0 &= ~JPEG_CONFR0_START;
+
+ tmpContext = hjpeg->Context;
+ /*Clear all context fileds execpt JPEG_CONTEXT_CONF_ENCODING and JPEG_CONTEXT_CUSTOM_TABLES*/
+ hjpeg->Context &= (JPEG_CONTEXT_CONF_ENCODING | JPEG_CONTEXT_CUSTOM_TABLES);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ /*Call End of Encoding/Decoding callback */
+ if ((tmpContext & JPEG_CONTEXT_OPERATION_MASK) == JPEG_CONTEXT_DECODE)
+ {
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DecodeCpltCallback(hjpeg);
+#else
+ HAL_JPEG_DecodeCpltCallback(hjpeg);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+ }
+ else /* JPEG_CONTEXT_ENCODE */
+ {
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->EncodeCpltCallback(hjpeg);
+#else
+ HAL_JPEG_EncodeCpltCallback(hjpeg);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+ }
+ }
+ else if ((hjpeg->Context & JPEG_CONTEXT_PAUSE_OUTPUT) == 0UL)
+ {
+ JPEG_DMA_PollResidualData(hjpeg);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+}
+
+/**
+ * @brief Poll residual output data when DMA process (encoding/decoding)
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval None.
+ */
+static void JPEG_DMA_PollResidualData(JPEG_HandleTypeDef *hjpeg)
+{
+ uint32_t tmpContext;
+ uint32_t count;
+ uint32_t dataOut;
+
+ for (count = JPEG_FIFO_SIZE; count > 0UL; count--)
+ {
+ if ((hjpeg->Context & JPEG_CONTEXT_PAUSE_OUTPUT) == 0UL)
+ {
+ if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_OFNEF) != 0UL)
+ {
+ dataOut = hjpeg->Instance->DOR;
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount] = (uint8_t)(dataOut & 0x000000FFUL);
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount + 1UL] = (uint8_t)((dataOut & 0x0000FF00UL) >> 8);
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount + 2UL] = (uint8_t)((dataOut & 0x00FF0000UL) >> 16);
+ hjpeg->pJpegOutBuffPtr[hjpeg->JpegOutCount + 3UL] = (uint8_t)((dataOut & 0xFF000000UL) >> 24);
+ hjpeg->JpegOutCount += 4UL;
+
+ if (hjpeg->JpegOutCount == hjpeg->OutDataLength)
+ {
+ /*Output Buffer is full, call HAL_JPEG_DataReadyCallback*/
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#else
+ HAL_JPEG_DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ hjpeg->JpegOutCount = 0;
+ }
+
+ }
+ }
+ }
+
+ tmpContext = hjpeg->Context;
+
+ if ((__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_OFNEF) == 0UL) || ((tmpContext & JPEG_CONTEXT_PAUSE_OUTPUT) == 0UL))
+ {
+ /*Stop Encoding/Decoding*/
+ hjpeg->Instance->CONFR0 &= ~JPEG_CONFR0_START;
+
+ if (hjpeg->JpegOutCount > 0UL)
+ {
+ /*Output Buffer is not empty, call DecodedDataReadyCallback*/
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#else
+ HAL_JPEG_DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ hjpeg->JpegOutCount = 0;
+ }
+
+ tmpContext = hjpeg->Context;
+ /*Clear all context fileds execpt JPEG_CONTEXT_CONF_ENCODING and JPEG_CONTEXT_CUSTOM_TABLES*/
+ hjpeg->Context &= (JPEG_CONTEXT_CONF_ENCODING | JPEG_CONTEXT_CUSTOM_TABLES);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hjpeg);
+
+ /* Change the JPEG state */
+ hjpeg->State = HAL_JPEG_STATE_READY;
+
+ /*Call End of Encoding/Decoding callback */
+ if ((tmpContext & JPEG_CONTEXT_OPERATION_MASK) == JPEG_CONTEXT_DECODE)
+ {
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DecodeCpltCallback(hjpeg);
+#else
+ HAL_JPEG_DecodeCpltCallback(hjpeg);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+ }
+ else /* JPEG_CONTEXT_ENCODE */
+ {
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->EncodeCpltCallback(hjpeg);
+#else
+ HAL_JPEG_EncodeCpltCallback(hjpeg);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @brief MDMA input transfer complete callback
+ * @param hmdma pointer to a MDMA_HandleTypeDef structure.
+ * @retval None
+ */
+static void JPEG_MDMAInCpltCallback(MDMA_HandleTypeDef *hmdma)
+{
+ uint32_t inXfrSize;
+
+ JPEG_HandleTypeDef *hjpeg = (JPEG_HandleTypeDef *)((MDMA_HandleTypeDef *)hmdma)->Parent;
+
+ /* Disable The JPEG IT so the MDMA Input Callback can not be interrupted by the JPEG EOC IT or JPEG HPD IT */
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_INTERRUPT_MASK);
+
+ /* Check if context method is DMA and we are not in ending DMA stage */
+ if ((hjpeg->Context & (JPEG_CONTEXT_METHOD_MASK | JPEG_CONTEXT_ENDING_DMA)) == JPEG_CONTEXT_DMA)
+ {
+
+ /*if the MDMA In is triggred with JPEG In FIFO Threshold flag
+ then MDMA In buffer size is 32 bytes
+ else (MDMA In is triggred with JPEG In FIFO not full flag)
+ then MDMA In buffer size is 4 bytes
+ */
+ inXfrSize = hjpeg->hdmain->Init.BufferTransferLength;
+
+ hjpeg->JpegInCount = hjpeg->InDataLength - (hmdma->Instance->CBNDTR & MDMA_CBNDTR_BNDT);
+
+ /*Call HAL_JPEG_GetDataCallback to get new data */
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->GetDataCallback(hjpeg, hjpeg->JpegInCount);
+#else
+ HAL_JPEG_GetDataCallback(hjpeg, hjpeg->JpegInCount);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+
+ if (hjpeg->InDataLength >= inXfrSize)
+ {
+ if (inXfrSize == 0UL)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->ErrorCallback(hjpeg);
+#else
+ HAL_JPEG_ErrorCallback(hjpeg);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+ return;
+ }
+ /*JPEG Input MDMA transfer data number must be multiple of MDMA buffer size
+ as the destination is a 32 bits register */
+ hjpeg->InDataLength = hjpeg->InDataLength - (hjpeg->InDataLength % inXfrSize);
+
+ }
+ else if (hjpeg->InDataLength > 0UL)
+ {
+ /* Transfer the remaining Data, must be multiple of source data size (byte) and destination data size (word) */
+ if ((hjpeg->InDataLength % 4UL) != 0UL)
+ {
+ hjpeg->InDataLength = ((hjpeg->InDataLength / 4UL) + 1UL) * 4UL;
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if (((hjpeg->Context & JPEG_CONTEXT_PAUSE_INPUT) == 0UL) && (hjpeg->InDataLength > 0UL))
+ {
+ /* Start MDMA FIFO In transfer */
+ if (HAL_MDMA_Start_IT(hjpeg->hdmain, (uint32_t)hjpeg->pJpegInBuffPtr, (uint32_t)&hjpeg->Instance->DIR,
+ hjpeg->InDataLength, 1) != HAL_OK)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->ErrorCallback(hjpeg);
+#else
+ HAL_JPEG_ErrorCallback(hjpeg);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+ return;
+ }
+ }
+
+ /* JPEG Conversion still on going : Enable the JPEG IT */
+ __HAL_JPEG_ENABLE_IT(hjpeg, JPEG_IT_EOC | JPEG_IT_HPD);
+ }
+}
+
+/**
+ * @brief MDMA output transfer complete callback
+ * @param hmdma pointer to a MDMA_HandleTypeDef structure.
+ * @retval None
+ */
+static void JPEG_MDMAOutCpltCallback(MDMA_HandleTypeDef *hmdma)
+{
+ JPEG_HandleTypeDef *hjpeg = (JPEG_HandleTypeDef *)((MDMA_HandleTypeDef *)hmdma)->Parent;
+
+
+ /* Disable The JPEG IT so the MDMA Output Callback can not be interrupted by the JPEG EOC IT or JPEG HPD IT */
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_INTERRUPT_MASK);
+
+ if ((hjpeg->Context & (JPEG_CONTEXT_METHOD_MASK | JPEG_CONTEXT_ENDING_DMA)) ==
+ JPEG_CONTEXT_DMA) /* Check if context method is DMA and we are not in ending DMA stage */
+ {
+ if (__HAL_JPEG_GET_FLAG(hjpeg, JPEG_FLAG_EOCF) == 0UL)
+ {
+ hjpeg->JpegOutCount = hjpeg->OutDataLength - (hmdma->Instance->CBNDTR & MDMA_CBNDTR_BNDT);
+
+ /*Output Buffer is full, call HAL_JPEG_DataReadyCallback*/
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#else
+ HAL_JPEG_DataReadyCallback(hjpeg, hjpeg->pJpegOutBuffPtr, hjpeg->JpegOutCount);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+
+ if ((hjpeg->Context & JPEG_CONTEXT_PAUSE_OUTPUT) == 0UL)
+ {
+ /* Start MDMA FIFO Out transfer */
+ if (HAL_MDMA_Start_IT(hjpeg->hdmaout, (uint32_t)&hjpeg->Instance->DOR, (uint32_t)hjpeg->pJpegOutBuffPtr,
+ hjpeg->OutDataLength, 1) != HAL_OK)
+ {
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+ hjpeg->State = HAL_JPEG_STATE_ERROR;
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->ErrorCallback(hjpeg);
+#else
+ HAL_JPEG_ErrorCallback(hjpeg);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+ return;
+ }
+ }
+ }
+
+ /* JPEG Conversion still on going : Enable the JPEG IT */
+ __HAL_JPEG_ENABLE_IT(hjpeg, JPEG_IT_EOC | JPEG_IT_HPD);
+ }
+
+}
+
+/**
+ * @brief MDMA Transfer error callback
+ * @param hmdma pointer to a MDMA_HandleTypeDef structure.
+ * @retval None
+ */
+static void JPEG_MDMAErrorCallback(MDMA_HandleTypeDef *hmdma)
+{
+ JPEG_HandleTypeDef *hjpeg = (JPEG_HandleTypeDef *)((MDMA_HandleTypeDef *)hmdma)->Parent;
+
+ /*Stop Encoding/Decoding*/
+ hjpeg->Instance->CONFR0 &= ~JPEG_CONFR0_START;
+
+ /* Disable All Interrupts */
+ __HAL_JPEG_DISABLE_IT(hjpeg, JPEG_INTERRUPT_MASK);
+
+ hjpeg->State = HAL_JPEG_STATE_READY;
+ hjpeg->ErrorCode |= HAL_JPEG_ERROR_DMA;
+
+#if (USE_HAL_JPEG_REGISTER_CALLBACKS == 1)
+ hjpeg->ErrorCallback(hjpeg);
+#else
+ HAL_JPEG_ErrorCallback(hjpeg);
+#endif /* USE_HAL_JPEG_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief MDMA output Abort callback
+ * @param hmdma pointer to a MDMA_HandleTypeDef structure.
+ * @retval None
+ */
+static void JPEG_MDMAOutAbortCallback(MDMA_HandleTypeDef *hmdma)
+{
+ JPEG_HandleTypeDef *hjpeg = (JPEG_HandleTypeDef *)((MDMA_HandleTypeDef *)hmdma)->Parent;
+
+ if ((hjpeg->Context & JPEG_CONTEXT_ENDING_DMA) != 0UL)
+ {
+ JPEG_DMA_EndProcess(hjpeg);
+ }
+}
+
+
+/**
+ * @brief Calculate the decoded image quality (from 1 to 100)
+ * @param hjpeg pointer to a JPEG_HandleTypeDef structure that contains
+ * the configuration information for JPEG module
+ * @retval JPEG image quality from 1 to 100.
+ */
+static uint32_t JPEG_GetQuality(JPEG_HandleTypeDef *hjpeg)
+{
+ uint32_t quality = 0;
+ uint32_t quantRow, quantVal, scale, i, j;
+ __IO uint32_t *tableAddress = hjpeg->Instance->QMEM0;
+
+ i = 0;
+ while (i < (JPEG_QUANT_TABLE_SIZE - 3UL))
+ {
+ quantRow = *tableAddress;
+ for (j = 0; j < 4UL; j++)
+ {
+ quantVal = (quantRow >> (8UL * j)) & 0xFFUL;
+ if (quantVal == 1UL)
+ {
+ /* if Quantization value = 1 then quality is 100%*/
+ quality += 100UL;
+ }
+ else
+ {
+ /* Note that the quantization coefficients must be specified in the table in zigzag order */
+ scale = (quantVal * 100UL) / ((uint32_t) hjpeg->QuantTable0[JPEG_ZIGZAG_ORDER[i + j]]);
+
+ if (scale <= 100UL)
+ {
+ quality += (200UL - scale) / 2UL;
+ }
+ else
+ {
+ quality += 5000UL / scale;
+ }
+ }
+ }
+
+ i += 4UL;
+ tableAddress ++;
+ }
+
+ return (quality / 64UL);
+}
+/**
+ * @}
+ */
+
+#endif /* JPEG */
+#endif /* HAL_JPEG_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_lptim.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_lptim.c
new file mode 100644
index 0000000000..5e03de3b94
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_lptim.c
@@ -0,0 +1,2540 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_lptim.c
+ * @author MCD Application Team
+ * @brief LPTIM HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Low Power Timer (LPTIM) peripheral:
+ * + Initialization and de-initialization functions.
+ * + Start/Stop operation functions in polling mode.
+ * + Start/Stop operation functions in interrupt mode.
+ * + Reading operation functions.
+ * + Peripheral State functions.
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The LPTIM HAL driver can be used as follows:
+
+ (#)Initialize the LPTIM low level resources by implementing the
+ HAL_LPTIM_MspInit():
+ (++) Enable the LPTIM interface clock using __HAL_RCC_LPTIMx_CLK_ENABLE().
+ (++) In case of using interrupts (e.g. HAL_LPTIM_PWM_Start_IT()):
+ (+++) Configure the LPTIM interrupt priority using HAL_NVIC_SetPriority().
+ (+++) Enable the LPTIM IRQ handler using HAL_NVIC_EnableIRQ().
+ (+++) In LPTIM IRQ handler, call HAL_LPTIM_IRQHandler().
+
+ (#)Initialize the LPTIM HAL using HAL_LPTIM_Init(). This function
+ configures mainly:
+ (++) The instance: LPTIM1 or LPTIM2.
+ (++) Clock: the counter clock.
+ (+++) Source : it can be either the ULPTIM input (IN1) or one of
+ the internal clock; (APB, LSE, LSI or MSI).
+ (+++) Prescaler: select the clock divider.
+ (++) UltraLowPowerClock : To be used only if the ULPTIM is selected
+ as counter clock source.
+ (+++) Polarity: polarity of the active edge for the counter unit
+ if the ULPTIM input is selected.
+ (+++) SampleTime: clock sampling time to configure the clock glitch
+ filter.
+ (++) Trigger: How the counter start.
+ (+++) Source: trigger can be software or one of the hardware triggers.
+ (+++) ActiveEdge : only for hardware trigger.
+ (+++) SampleTime : trigger sampling time to configure the trigger
+ glitch filter.
+ (++) OutputPolarity : 2 opposite polarities are possible.
+ (++) UpdateMode: specifies whether the update of the autoreload and
+ the compare values is done immediately or after the end of current
+ period.
+ (++) Input1Source: Source selected for input1 (GPIO or comparator output).
+ (++) Input2Source: Source selected for input2 (GPIO or comparator output).
+ Input2 is used only for encoder feature so is used only for LPTIM1 instance.
+
+ (#)Six modes are available:
+
+ (++) PWM Mode: To generate a PWM signal with specified period and pulse,
+ call HAL_LPTIM_PWM_Start() or HAL_LPTIM_PWM_Start_IT() for interruption
+ mode.
+
+ (++) One Pulse Mode: To generate pulse with specified width in response
+ to a stimulus, call HAL_LPTIM_OnePulse_Start() or
+ HAL_LPTIM_OnePulse_Start_IT() for interruption mode.
+
+ (++) Set once Mode: In this mode, the output changes the level (from
+ low level to high level if the output polarity is configured high, else
+ the opposite) when a compare match occurs. To start this mode, call
+ HAL_LPTIM_SetOnce_Start() or HAL_LPTIM_SetOnce_Start_IT() for
+ interruption mode.
+
+ (++) Encoder Mode: To use the encoder interface call
+ HAL_LPTIM_Encoder_Start() or HAL_LPTIM_Encoder_Start_IT() for
+ interruption mode. Only available for LPTIM1 instance.
+
+ (++) Time out Mode: an active edge on one selected trigger input rests
+ the counter. The first trigger event will start the timer, any
+ successive trigger event will reset the counter and the timer will
+ restart. To start this mode call HAL_LPTIM_TimeOut_Start_IT() or
+ HAL_LPTIM_TimeOut_Start_IT() for interruption mode.
+
+ (++) Counter Mode: counter can be used to count external events on
+ the LPTIM Input1 or it can be used to count internal clock cycles.
+ To start this mode, call HAL_LPTIM_Counter_Start() or
+ HAL_LPTIM_Counter_Start_IT() for interruption mode.
+
+
+ (#) User can stop any process by calling the corresponding API:
+ HAL_LPTIM_Xxx_Stop() or HAL_LPTIM_Xxx_Stop_IT() if the process is
+ already started in interruption mode.
+
+ (#) De-initialize the LPTIM peripheral using HAL_LPTIM_DeInit().
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_LPTIM_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ [..]
+ Use Function @ref HAL_LPTIM_RegisterCallback() to register a callback.
+ @ref HAL_LPTIM_RegisterCallback() takes as parameters the HAL peripheral handle,
+ the Callback ID and a pointer to the user callback function.
+ [..]
+ Use function @ref HAL_LPTIM_UnRegisterCallback() to reset a callback to the
+ default weak function.
+ @ref HAL_LPTIM_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ [..]
+ These functions allow to register/unregister following callbacks:
+
+ (+) MspInitCallback : LPTIM Base Msp Init Callback.
+ (+) MspDeInitCallback : LPTIM Base Msp DeInit Callback.
+ (+) CompareMatchCallback : Compare match Callback.
+ (+) AutoReloadMatchCallback : Auto-reload match Callback.
+ (+) TriggerCallback : External trigger event detection Callback.
+ (+) CompareWriteCallback : Compare register write complete Callback.
+ (+) AutoReloadWriteCallback : Auto-reload register write complete Callback.
+ (+) DirectionUpCallback : Up-counting direction change Callback.
+ (+) DirectionDownCallback : Down-counting direction change Callback.
+
+ [..]
+ By default, after the Init and when the state is HAL_LPTIM_STATE_RESET
+ all interrupt callbacks are set to the corresponding weak functions:
+ examples @ref HAL_LPTIM_TriggerCallback(), @ref HAL_LPTIM_CompareMatchCallback().
+
+ [..]
+ 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_LPTIM_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_LPTIM_STATE_READY or HAL_LPTIM_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 @ref HAL_LPTIM_RegisterCallback() before calling DeInit or Init function.
+
+ [..]
+ When The compilation define USE_HAL_LPTIM_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup LPTIM LPTIM
+ * @brief LPTIM HAL module driver.
+ * @{
+ */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+
+#if defined (LPTIM1) || defined (LPTIM2) || defined (LPTIM3) || defined (LPTIM4) || defined (LPTIM5)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup LPTIM_Private_Constants
+ * @{
+ */
+#define TIMEOUT 1000UL /* Timeout is 1s */
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+static void LPTIM_ResetCallback(LPTIM_HandleTypeDef *lptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+static HAL_StatusTypeDef LPTIM_WaitForFlag(LPTIM_HandleTypeDef *hlptim, uint32_t flag);
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup LPTIM_Exported_Functions LPTIM Exported Functions
+ * @{
+ */
+
+/** @defgroup LPTIM_Exported_Functions_Group1 Initialization/de-initialization functions
+ * @brief Initialization and Configuration functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the LPTIM according to the specified parameters in the
+ LPTIM_InitTypeDef and initialize the associated handle.
+ (+) DeInitialize the LPTIM peripheral.
+ (+) Initialize the LPTIM MSP.
+ (+) DeInitialize the LPTIM MSP.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the LPTIM according to the specified parameters in the
+ * LPTIM_InitTypeDef and initialize the associated handle.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_Init(LPTIM_HandleTypeDef *hlptim)
+{
+ uint32_t tmpcfgr;
+
+ /* Check the LPTIM handle allocation */
+ if (hlptim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ assert_param(IS_LPTIM_CLOCK_SOURCE(hlptim->Init.Clock.Source));
+ assert_param(IS_LPTIM_CLOCK_PRESCALER(hlptim->Init.Clock.Prescaler));
+ if (hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_ULPTIM)
+ {
+ assert_param(IS_LPTIM_CLOCK_POLARITY(hlptim->Init.UltraLowPowerClock.Polarity));
+ }
+ assert_param(IS_LPTIM_TRG_SOURCE(hlptim->Init.Trigger.Source));
+ if (hlptim->Init.Trigger.Source != LPTIM_TRIGSOURCE_SOFTWARE)
+ {
+ assert_param(IS_LPTIM_EXT_TRG_POLARITY(hlptim->Init.Trigger.ActiveEdge));
+ }
+ if (hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC)
+ {
+ assert_param(IS_LPTIM_TRIG_SAMPLE_TIME(hlptim->Init.Trigger.SampleTime));
+ assert_param(IS_LPTIM_CLOCK_SAMPLE_TIME(hlptim->Init.UltraLowPowerClock.SampleTime));
+ }
+ assert_param(IS_LPTIM_OUTPUT_POLARITY(hlptim->Init.OutputPolarity));
+ assert_param(IS_LPTIM_UPDATE_MODE(hlptim->Init.UpdateMode));
+ assert_param(IS_LPTIM_COUNTER_SOURCE(hlptim->Init.CounterSource));
+
+ if (hlptim->State == HAL_LPTIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hlptim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+ /* Reset interrupt callbacks to legacy weak callbacks */
+ LPTIM_ResetCallback(hlptim);
+
+ if (hlptim->MspInitCallback == NULL)
+ {
+ hlptim->MspInitCallback = HAL_LPTIM_MspInit;
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ hlptim->MspInitCallback(hlptim);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ HAL_LPTIM_MspInit(hlptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+ }
+
+ /* Change the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Get the LPTIMx CFGR value */
+ tmpcfgr = hlptim->Instance->CFGR;
+
+ if (hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_ULPTIM)
+ {
+ tmpcfgr &= (uint32_t)(~(LPTIM_CFGR_CKPOL));
+ }
+ if (hlptim->Init.Trigger.Source != LPTIM_TRIGSOURCE_SOFTWARE)
+ {
+ tmpcfgr &= (uint32_t)(~(LPTIM_CFGR_TRIGSEL));
+ }
+ if (hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC)
+ {
+ tmpcfgr &= (uint32_t)(~(LPTIM_CFGR_TRGFLT | LPTIM_CFGR_CKFLT));
+ }
+
+ /* Clear CKSEL, CKPOL, PRESC, TRIGEN, TRGFLT, WAVPOL, PRELOAD & COUNTMODE bits */
+ tmpcfgr &= (uint32_t)(~(LPTIM_CFGR_CKSEL | LPTIM_CFGR_CKPOL | LPTIM_CFGR_TRIGEN | LPTIM_CFGR_PRELOAD |
+ LPTIM_CFGR_WAVPOL | LPTIM_CFGR_PRESC | LPTIM_CFGR_COUNTMODE));
+
+ /* Set initialization parameters */
+ tmpcfgr |= (hlptim->Init.Clock.Source |
+ hlptim->Init.Clock.Prescaler |
+ hlptim->Init.OutputPolarity |
+ hlptim->Init.UpdateMode |
+ hlptim->Init.CounterSource);
+
+ /* Glitch filters for internal triggers and external inputs are configured
+ * only if an internal clock source is provided to the LPTIM
+ */
+ if (hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC)
+ {
+ tmpcfgr |= (hlptim->Init.Trigger.SampleTime |
+ hlptim->Init.UltraLowPowerClock.SampleTime);
+ }
+
+ /* Configure the active edge or edges used by the counter only if LPTIM is
+ * clocked by an external clock source
+ */
+ if (hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_ULPTIM)
+ {
+ tmpcfgr |= (hlptim->Init.UltraLowPowerClock.Polarity);
+ }
+
+ if (hlptim->Init.Trigger.Source != LPTIM_TRIGSOURCE_SOFTWARE)
+ {
+ /* Enable External trigger and set the trigger source */
+ tmpcfgr |= (hlptim->Init.Trigger.Source |
+ hlptim->Init.Trigger.ActiveEdge);
+ }
+
+ /* Write to LPTIMx CFGR */
+ hlptim->Instance->CFGR = tmpcfgr;
+
+ /* Configure LPTIM input sources */
+ if ((hlptim->Instance == LPTIM1) || (hlptim->Instance == LPTIM2))
+ {
+ /* Check LPTIM Input1 and Input2 sources */
+ assert_param(IS_LPTIM_INPUT1_SOURCE(hlptim->Instance, hlptim->Init.Input1Source));
+ assert_param(IS_LPTIM_INPUT2_SOURCE(hlptim->Instance, hlptim->Init.Input2Source));
+
+ /* Configure LPTIM Input1 and Input2 sources */
+ hlptim->Instance->CFGR2 = (hlptim->Init.Input1Source | hlptim->Init.Input2Source);
+ }
+ else
+ {
+ if (hlptim->Instance == LPTIM3)
+ {
+ /* Check LPTIM3 Input1 source */
+ assert_param(IS_LPTIM_INPUT1_SOURCE(hlptim->Instance, hlptim->Init.Input1Source));
+
+ /* Configure LPTIM3 Input1 source */
+ hlptim->Instance->CFGR2 = hlptim->Init.Input1Source;
+ }
+ }
+
+ /* Change the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the LPTIM peripheral.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_DeInit(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the LPTIM handle allocation */
+ if (hlptim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Change the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the LPTIM Peripheral Clock */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+ if (hlptim->MspDeInitCallback == NULL)
+ {
+ hlptim->MspDeInitCallback = HAL_LPTIM_MspDeInit;
+ }
+
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ hlptim->MspDeInitCallback(hlptim);
+#else
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ HAL_LPTIM_MspDeInit(hlptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+
+ /* Change the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hlptim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the LPTIM MSP.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+__weak void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hlptim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LPTIM_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize LPTIM MSP.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+__weak void HAL_LPTIM_MspDeInit(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hlptim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LPTIM_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup LPTIM_Exported_Functions_Group2 LPTIM Start-Stop operation functions
+ * @brief Start-Stop operation functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### LPTIM Start Stop operation functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start the PWM mode.
+ (+) Stop the PWM mode.
+ (+) Start the One pulse mode.
+ (+) Stop the One pulse mode.
+ (+) Start the Set once mode.
+ (+) Stop the Set once mode.
+ (+) Start the Encoder mode.
+ (+) Stop the Encoder mode.
+ (+) Start the Timeout mode.
+ (+) Stop the Timeout mode.
+ (+) Start the Counter mode.
+ (+) Stop the Counter mode.
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the LPTIM PWM generation.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param Pulse Specifies the compare value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_PWM_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(IS_LPTIM_PULSE(Pulse));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Reset WAVE bit to set PWM mode */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_WAVE;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+
+ /* Load the pulse value in the compare register */
+ __HAL_LPTIM_COMPARE_SET(hlptim, Pulse);
+
+ /* Wait for the completion of the write operation to the LPTIM_CMP register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Start timer in continuous mode */
+ __HAL_LPTIM_START_CONTINUOUS(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the LPTIM PWM generation.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_PWM_Stop(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the LPTIM PWM generation in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF
+ * @param Pulse Specifies the compare value.
+ * This parameter must be a value between 0x0000 and 0xFFFF
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_PWM_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(IS_LPTIM_PULSE(Pulse));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Reset WAVE bit to set PWM mode */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_WAVE;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+
+ /* Load the pulse value in the compare register */
+ __HAL_LPTIM_COMPARE_SET(hlptim, Pulse);
+
+ /* Wait for the completion of the write operation to the LPTIM_CMP register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Enable Autoreload write complete interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARROK);
+
+ /* Enable Compare write complete interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPOK);
+
+ /* Enable Autoreload match interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM);
+
+ /* Enable Compare match interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPM);
+
+ /* If external trigger source is used, then enable external trigger interrupt */
+ if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE)
+ {
+ /* Enable external trigger interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_EXTTRIG);
+ }
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Start timer in continuous mode */
+ __HAL_LPTIM_START_CONTINUOUS(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the LPTIM PWM generation in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_PWM_Stop_IT(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable Autoreload write complete interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARROK);
+
+ /* Disable Compare write complete interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPOK);
+
+ /* Disable Autoreload match interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARRM);
+
+ /* Disable Compare match interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPM);
+
+ /* If external trigger source is used, then disable external trigger interrupt */
+ if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE)
+ {
+ /* Disable external trigger interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_EXTTRIG);
+ }
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the LPTIM One pulse generation.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param Pulse Specifies the compare value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_OnePulse_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(IS_LPTIM_PULSE(Pulse));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Reset WAVE bit to set one pulse mode */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_WAVE;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+
+ /* Load the pulse value in the compare register */
+ __HAL_LPTIM_COMPARE_SET(hlptim, Pulse);
+
+ /* Wait for the completion of the write operation to the LPTIM_CMP register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Start timer in single (one shot) mode */
+ __HAL_LPTIM_START_SINGLE(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the LPTIM One pulse generation.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_OnePulse_Stop(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the LPTIM One pulse generation in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param Pulse Specifies the compare value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_OnePulse_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(IS_LPTIM_PULSE(Pulse));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Reset WAVE bit to set one pulse mode */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_WAVE;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+
+ /* Load the pulse value in the compare register */
+ __HAL_LPTIM_COMPARE_SET(hlptim, Pulse);
+
+ /* Wait for the completion of the write operation to the LPTIM_CMP register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Enable Autoreload write complete interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARROK);
+
+ /* Enable Compare write complete interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPOK);
+
+ /* Enable Autoreload match interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM);
+
+ /* Enable Compare match interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPM);
+
+ /* If external trigger source is used, then enable external trigger interrupt */
+ if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE)
+ {
+ /* Enable external trigger interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_EXTTRIG);
+ }
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Start timer in single (one shot) mode */
+ __HAL_LPTIM_START_SINGLE(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the LPTIM One pulse generation in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_OnePulse_Stop_IT(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable Autoreload write complete interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARROK);
+
+ /* Disable Compare write complete interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPOK);
+
+ /* Disable Autoreload match interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARRM);
+
+ /* Disable Compare match interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPM);
+
+ /* If external trigger source is used, then disable external trigger interrupt */
+ if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE)
+ {
+ /* Disable external trigger interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_EXTTRIG);
+ }
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the LPTIM in Set once mode.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param Pulse Specifies the compare value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_SetOnce_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(IS_LPTIM_PULSE(Pulse));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Set WAVE bit to enable the set once mode */
+ hlptim->Instance->CFGR |= LPTIM_CFGR_WAVE;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+
+ /* Load the pulse value in the compare register */
+ __HAL_LPTIM_COMPARE_SET(hlptim, Pulse);
+
+ /* Wait for the completion of the write operation to the LPTIM_CMP register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Start timer in single (one shot) mode */
+ __HAL_LPTIM_START_SINGLE(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the LPTIM Set once mode.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_SetOnce_Stop(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the LPTIM Set once mode in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param Pulse Specifies the compare value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_SetOnce_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(IS_LPTIM_PULSE(Pulse));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Set WAVE bit to enable the set once mode */
+ hlptim->Instance->CFGR |= LPTIM_CFGR_WAVE;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+
+ /* Load the pulse value in the compare register */
+ __HAL_LPTIM_COMPARE_SET(hlptim, Pulse);
+
+ /* Wait for the completion of the write operation to the LPTIM_CMP register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Enable Autoreload write complete interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARROK);
+
+ /* Enable Compare write complete interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPOK);
+
+ /* Enable Autoreload match interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM);
+
+ /* Enable Compare match interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPM);
+
+ /* If external trigger source is used, then enable external trigger interrupt */
+ if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE)
+ {
+ /* Enable external trigger interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_EXTTRIG);
+ }
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Start timer in single (one shot) mode */
+ __HAL_LPTIM_START_SINGLE(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the LPTIM Set once mode in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_SetOnce_Stop_IT(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable Autoreload write complete interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARROK);
+
+ /* Disable Compare write complete interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPOK);
+
+ /* Disable Autoreload match interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARRM);
+
+ /* Disable Compare match interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPM);
+
+ /* If external trigger source is used, then disable external trigger interrupt */
+ if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE)
+ {
+ /* Disable external trigger interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_EXTTRIG);
+ }
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the Encoder interface.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_Encoder_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period)
+{
+ uint32_t tmpcfgr;
+
+ /* Check the parameters */
+ assert_param(IS_LPTIM_ENCODER_INTERFACE_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC);
+ assert_param(hlptim->Init.Clock.Prescaler == LPTIM_PRESCALER_DIV1);
+ assert_param(IS_LPTIM_CLOCK_POLARITY(hlptim->Init.UltraLowPowerClock.Polarity));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Get the LPTIMx CFGR value */
+ tmpcfgr = hlptim->Instance->CFGR;
+
+ /* Clear CKPOL bits */
+ tmpcfgr &= (uint32_t)(~LPTIM_CFGR_CKPOL);
+
+ /* Set Input polarity */
+ tmpcfgr |= hlptim->Init.UltraLowPowerClock.Polarity;
+
+ /* Write to LPTIMx CFGR */
+ hlptim->Instance->CFGR = tmpcfgr;
+
+ /* Set ENC bit to enable the encoder interface */
+ hlptim->Instance->CFGR |= LPTIM_CFGR_ENC;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Start timer in continuous mode */
+ __HAL_LPTIM_START_CONTINUOUS(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the Encoder interface.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_Encoder_Stop(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_ENCODER_INTERFACE_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Reset ENC bit to disable the encoder interface */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_ENC;
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the Encoder interface in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_Encoder_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period)
+{
+ uint32_t tmpcfgr;
+
+ /* Check the parameters */
+ assert_param(IS_LPTIM_ENCODER_INTERFACE_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC);
+ assert_param(hlptim->Init.Clock.Prescaler == LPTIM_PRESCALER_DIV1);
+ assert_param(IS_LPTIM_CLOCK_POLARITY(hlptim->Init.UltraLowPowerClock.Polarity));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Configure edge sensitivity for encoder mode */
+ /* Get the LPTIMx CFGR value */
+ tmpcfgr = hlptim->Instance->CFGR;
+
+ /* Clear CKPOL bits */
+ tmpcfgr &= (uint32_t)(~LPTIM_CFGR_CKPOL);
+
+ /* Set Input polarity */
+ tmpcfgr |= hlptim->Init.UltraLowPowerClock.Polarity;
+
+ /* Write to LPTIMx CFGR */
+ hlptim->Instance->CFGR = tmpcfgr;
+
+ /* Set ENC bit to enable the encoder interface */
+ hlptim->Instance->CFGR |= LPTIM_CFGR_ENC;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Enable "switch to down direction" interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_DOWN);
+
+ /* Enable "switch to up direction" interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_UP);
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Start timer in continuous mode */
+ __HAL_LPTIM_START_CONTINUOUS(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the Encoder interface in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_Encoder_Stop_IT(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_ENCODER_INTERFACE_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Reset ENC bit to disable the encoder interface */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_ENC;
+
+ /* Disable "switch to down direction" interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_DOWN);
+
+ /* Disable "switch to up direction" interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_UP);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the Timeout function.
+ * @note The first trigger event will start the timer, any successive
+ * trigger event will reset the counter and the timer restarts.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param Timeout Specifies the TimeOut value to reset the counter.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_TimeOut_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Timeout)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(IS_LPTIM_PULSE(Timeout));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Set TIMOUT bit to enable the timeout function */
+ hlptim->Instance->CFGR |= LPTIM_CFGR_TIMOUT;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+
+ /* Load the Timeout value in the compare register */
+ __HAL_LPTIM_COMPARE_SET(hlptim, Timeout);
+
+ /* Wait for the completion of the write operation to the LPTIM_CMP register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Start timer in continuous mode */
+ __HAL_LPTIM_START_CONTINUOUS(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the Timeout function.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_TimeOut_Stop(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Reset TIMOUT bit to enable the timeout function */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_TIMOUT;
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the Timeout function in interrupt mode.
+ * @note The first trigger event will start the timer, any successive
+ * trigger event will reset the counter and the timer restarts.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param Timeout Specifies the TimeOut value to reset the counter.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_TimeOut_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Timeout)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+ assert_param(IS_LPTIM_PULSE(Timeout));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Set TIMOUT bit to enable the timeout function */
+ hlptim->Instance->CFGR |= LPTIM_CFGR_TIMOUT;
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+
+ /* Load the Timeout value in the compare register */
+ __HAL_LPTIM_COMPARE_SET(hlptim, Timeout);
+
+ /* Wait for the completion of the write operation to the LPTIM_CMP register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Enable Compare match interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPM);
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Start timer in continuous mode */
+ __HAL_LPTIM_START_CONTINUOUS(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the Timeout function in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_TimeOut_Stop_IT(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Reset TIMOUT bit to enable the timeout function */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_TIMOUT;
+
+ /* Disable Compare match interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPM);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the Counter mode.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_Counter_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* If clock source is not ULPTIM clock and counter source is external, then it must not be prescaled */
+ if ((hlptim->Init.Clock.Source != LPTIM_CLOCKSOURCE_ULPTIM) && (hlptim->Init.CounterSource == LPTIM_COUNTERSOURCE_EXTERNAL))
+ {
+ /* Check if clock is prescaled */
+ assert_param(IS_LPTIM_CLOCK_PRESCALERDIV1(hlptim->Init.Clock.Prescaler));
+ /* Set clock prescaler to 0 */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_PRESC;
+ }
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Start timer in continuous mode */
+ __HAL_LPTIM_START_CONTINUOUS(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the Counter mode.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_Counter_Stop(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Start the Counter mode in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @param Period Specifies the Autoreload value.
+ * This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_Counter_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+ assert_param(IS_LPTIM_PERIOD(Period));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* If clock source is not ULPTIM clock and counter source is external, then it must not be prescaled */
+ if ((hlptim->Init.Clock.Source != LPTIM_CLOCKSOURCE_ULPTIM) && (hlptim->Init.CounterSource == LPTIM_COUNTERSOURCE_EXTERNAL))
+ {
+ /* Check if clock is prescaled */
+ assert_param(IS_LPTIM_CLOCK_PRESCALERDIV1(hlptim->Init.Clock.Prescaler));
+ /* Set clock prescaler to 0 */
+ hlptim->Instance->CFGR &= ~LPTIM_CFGR_PRESC;
+ }
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Clear flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Load the period value in the autoreload register */
+ __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period);
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Enable Autoreload write complete interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARROK);
+
+ /* Enable Autoreload match interrupt */
+ __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM);
+
+ /* Enable the Peripheral */
+ __HAL_LPTIM_ENABLE(hlptim);
+
+ /* Start timer in continuous mode */
+ __HAL_LPTIM_START_CONTINUOUS(hlptim);
+
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the Counter mode in interrupt mode.
+ * @param hlptim LPTIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LPTIM_Counter_Stop_IT(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ /* Set the LPTIM state */
+ hlptim->State = HAL_LPTIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_LPTIM_DISABLE(hlptim);
+
+ if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable Autoreload write complete interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARROK);
+
+ /* Disable Autoreload match interrupt */
+ __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARRM);
+ /* Change the TIM state*/
+ hlptim->State = HAL_LPTIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup LPTIM_Exported_Functions_Group3 LPTIM Read operation functions
+ * @brief Read operation functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### LPTIM Read operation functions #####
+ ==============================================================================
+[..] This section provides LPTIM Reading functions.
+ (+) Read the counter value.
+ (+) Read the period (Auto-reload) value.
+ (+) Read the pulse (Compare)value.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the current counter value.
+ * @param hlptim LPTIM handle
+ * @retval Counter value.
+ */
+uint32_t HAL_LPTIM_ReadCounter(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ return (hlptim->Instance->CNT);
+}
+
+/**
+ * @brief Return the current Autoreload (Period) value.
+ * @param hlptim LPTIM handle
+ * @retval Autoreload value.
+ */
+uint32_t HAL_LPTIM_ReadAutoReload(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ return (hlptim->Instance->ARR);
+}
+
+/**
+ * @brief Return the current Compare (Pulse) value.
+ * @param hlptim LPTIM handle
+ * @retval Compare value.
+ */
+uint32_t HAL_LPTIM_ReadCompare(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(hlptim->Instance));
+
+ return (hlptim->Instance->CMP);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup LPTIM_Exported_Functions_Group4 LPTIM IRQ handler and callbacks
+ * @brief LPTIM IRQ handler.
+ *
+@verbatim
+ ==============================================================================
+ ##### LPTIM IRQ handler and callbacks #####
+ ==============================================================================
+[..] This section provides LPTIM IRQ handler and callback functions called within
+ the IRQ handler:
+ (+) LPTIM interrupt request handler
+ (+) Compare match Callback
+ (+) Auto-reload match Callback
+ (+) External trigger event detection Callback
+ (+) Compare register write complete Callback
+ (+) Auto-reload register write complete Callback
+ (+) Up-counting direction change Callback
+ (+) Down-counting direction change Callback
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Handle LPTIM interrupt request.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+void HAL_LPTIM_IRQHandler(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Compare match interrupt */
+ if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_CMPM) != RESET)
+ {
+ if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_CMPM) != RESET)
+ {
+ /* Clear Compare match flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPM);
+
+ /* Compare match Callback */
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+ hlptim->CompareMatchCallback(hlptim);
+#else
+ HAL_LPTIM_CompareMatchCallback(hlptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Autoreload match interrupt */
+ if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_ARRM) != RESET)
+ {
+ if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_ARRM) != RESET)
+ {
+ /* Clear Autoreload match flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARRM);
+
+ /* Autoreload match Callback */
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+ hlptim->AutoReloadMatchCallback(hlptim);
+#else
+ HAL_LPTIM_AutoReloadMatchCallback(hlptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Trigger detected interrupt */
+ if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_EXTTRIG) != RESET)
+ {
+ if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_EXTTRIG) != RESET)
+ {
+ /* Clear Trigger detected flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_EXTTRIG);
+
+ /* Trigger detected callback */
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+ hlptim->TriggerCallback(hlptim);
+#else
+ HAL_LPTIM_TriggerCallback(hlptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Compare write interrupt */
+ if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_CMPOK) != RESET)
+ {
+ if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_CMPOK) != RESET)
+ {
+ /* Clear Compare write flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+
+ /* Compare write Callback */
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+ hlptim->CompareWriteCallback(hlptim);
+#else
+ HAL_LPTIM_CompareWriteCallback(hlptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Autoreload write interrupt */
+ if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_ARROK) != RESET)
+ {
+ if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_ARROK) != RESET)
+ {
+ /* Clear Autoreload write flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+
+ /* Autoreload write Callback */
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+ hlptim->AutoReloadWriteCallback(hlptim);
+#else
+ HAL_LPTIM_AutoReloadWriteCallback(hlptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Direction counter changed from Down to Up interrupt */
+ if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_UP) != RESET)
+ {
+ if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_UP) != RESET)
+ {
+ /* Clear Direction counter changed from Down to Up flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_UP);
+
+ /* Direction counter changed from Down to Up Callback */
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+ hlptim->DirectionUpCallback(hlptim);
+#else
+ HAL_LPTIM_DirectionUpCallback(hlptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Direction counter changed from Up to Down interrupt */
+ if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_DOWN) != RESET)
+ {
+ if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_DOWN) != RESET)
+ {
+ /* Clear Direction counter changed from Up to Down flag */
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_DOWN);
+
+ /* Direction counter changed from Up to Down Callback */
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+ hlptim->DirectionDownCallback(hlptim);
+#else
+ HAL_LPTIM_DirectionDownCallback(hlptim);
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @brief Compare match callback in non-blocking mode.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+__weak void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hlptim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LPTIM_CompareMatchCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Autoreload match callback in non-blocking mode.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+__weak void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hlptim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LPTIM_AutoReloadMatchCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Trigger detected callback in non-blocking mode.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+__weak void HAL_LPTIM_TriggerCallback(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hlptim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LPTIM_TriggerCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Compare write callback in non-blocking mode.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+__weak void HAL_LPTIM_CompareWriteCallback(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hlptim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LPTIM_CompareWriteCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Autoreload write callback in non-blocking mode.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+__weak void HAL_LPTIM_AutoReloadWriteCallback(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hlptim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LPTIM_AutoReloadWriteCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Direction counter changed from Down to Up callback in non-blocking mode.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+__weak void HAL_LPTIM_DirectionUpCallback(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hlptim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LPTIM_DirectionUpCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Direction counter changed from Up to Down callback in non-blocking mode.
+ * @param hlptim LPTIM handle
+ * @retval None
+ */
+__weak void HAL_LPTIM_DirectionDownCallback(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hlptim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LPTIM_DirectionDownCallback could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User LPTIM callback to be used instead of the weak predefined callback
+ * @param hlptim LPTIM handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_LPTIM_MSPINIT_CB_ID LPTIM Base Msp Init Callback ID
+ * @arg @ref HAL_LPTIM_MSPDEINIT_CB_ID LPTIM Base Msp DeInit Callback ID
+ * @arg @ref HAL_LPTIM_COMPARE_MATCH_CB_ID Compare match Callback ID
+ * @arg @ref HAL_LPTIM_AUTORELOAD_MATCH_CB_ID Auto-reload match Callback ID
+ * @arg @ref HAL_LPTIM_TRIGGER_CB_ID External trigger event detection Callback ID
+ * @arg @ref HAL_LPTIM_COMPARE_WRITE_CB_ID Compare register write complete Callback ID
+ * @arg @ref HAL_LPTIM_AUTORELOAD_WRITE_CB_ID Auto-reload register write complete Callback ID
+ * @arg @ref HAL_LPTIM_DIRECTION_UP_CB_ID Up-counting direction change Callback ID
+ * @arg @ref HAL_LPTIM_DIRECTION_DOWN_CB_ID Down-counting direction change Callback ID
+ * @param pCallback pointer to the callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_LPTIM_RegisterCallback(LPTIM_HandleTypeDef *hlptim,
+ HAL_LPTIM_CallbackIDTypeDef CallbackID,
+ pLPTIM_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hlptim);
+
+ if (hlptim->State == HAL_LPTIM_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_LPTIM_MSPINIT_CB_ID :
+ hlptim->MspInitCallback = pCallback;
+ break;
+
+ case HAL_LPTIM_MSPDEINIT_CB_ID :
+ hlptim->MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_LPTIM_COMPARE_MATCH_CB_ID :
+ hlptim->CompareMatchCallback = pCallback;
+ break;
+
+ case HAL_LPTIM_AUTORELOAD_MATCH_CB_ID :
+ hlptim->AutoReloadMatchCallback = pCallback;
+ break;
+
+ case HAL_LPTIM_TRIGGER_CB_ID :
+ hlptim->TriggerCallback = pCallback;
+ break;
+
+ case HAL_LPTIM_COMPARE_WRITE_CB_ID :
+ hlptim->CompareWriteCallback = pCallback;
+ break;
+
+ case HAL_LPTIM_AUTORELOAD_WRITE_CB_ID :
+ hlptim->AutoReloadWriteCallback = pCallback;
+ break;
+
+ case HAL_LPTIM_DIRECTION_UP_CB_ID :
+ hlptim->DirectionUpCallback = pCallback;
+ break;
+
+ case HAL_LPTIM_DIRECTION_DOWN_CB_ID :
+ hlptim->DirectionDownCallback = pCallback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hlptim->State == HAL_LPTIM_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_LPTIM_MSPINIT_CB_ID :
+ hlptim->MspInitCallback = pCallback;
+ break;
+
+ case HAL_LPTIM_MSPDEINIT_CB_ID :
+ hlptim->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hlptim);
+
+ return status;
+}
+
+/**
+ * @brief Unregister a LPTIM callback
+ * LLPTIM callback is redirected to the weak predefined callback
+ * @param hlptim LPTIM handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_LPTIM_MSPINIT_CB_ID LPTIM Base Msp Init Callback ID
+ * @arg @ref HAL_LPTIM_MSPDEINIT_CB_ID LPTIM Base Msp DeInit Callback ID
+ * @arg @ref HAL_LPTIM_COMPARE_MATCH_CB_ID Compare match Callback ID
+ * @arg @ref HAL_LPTIM_AUTORELOAD_MATCH_CB_ID Auto-reload match Callback ID
+ * @arg @ref HAL_LPTIM_TRIGGER_CB_ID External trigger event detection Callback ID
+ * @arg @ref HAL_LPTIM_COMPARE_WRITE_CB_ID Compare register write complete Callback ID
+ * @arg @ref HAL_LPTIM_AUTORELOAD_WRITE_CB_ID Auto-reload register write complete Callback ID
+ * @arg @ref HAL_LPTIM_DIRECTION_UP_CB_ID Up-counting direction change Callback ID
+ * @arg @ref HAL_LPTIM_DIRECTION_DOWN_CB_ID Down-counting direction change Callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_LPTIM_UnRegisterCallback(LPTIM_HandleTypeDef *hlptim,
+ HAL_LPTIM_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hlptim);
+
+ if (hlptim->State == HAL_LPTIM_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_LPTIM_MSPINIT_CB_ID :
+ hlptim->MspInitCallback = HAL_LPTIM_MspInit; /* Legacy weak MspInit Callback */
+ break;
+
+ case HAL_LPTIM_MSPDEINIT_CB_ID :
+ hlptim->MspDeInitCallback = HAL_LPTIM_MspDeInit; /* Legacy weak Msp DeInit Callback */
+ break;
+
+ case HAL_LPTIM_COMPARE_MATCH_CB_ID :
+ hlptim->CompareMatchCallback = HAL_LPTIM_CompareMatchCallback; /* Legacy weak Compare match Callback */
+ break;
+
+ case HAL_LPTIM_AUTORELOAD_MATCH_CB_ID :
+ hlptim->AutoReloadMatchCallback = HAL_LPTIM_AutoReloadMatchCallback; /* Legacy weak Auto-reload match Callback */
+ break;
+
+ case HAL_LPTIM_TRIGGER_CB_ID :
+ hlptim->TriggerCallback = HAL_LPTIM_TriggerCallback; /* Legacy weak External trigger event detection Callback */
+ break;
+
+ case HAL_LPTIM_COMPARE_WRITE_CB_ID :
+ hlptim->CompareWriteCallback = HAL_LPTIM_CompareWriteCallback; /* Legacy weak Compare register write complete Callback */
+ break;
+
+ case HAL_LPTIM_AUTORELOAD_WRITE_CB_ID :
+ hlptim->AutoReloadWriteCallback = HAL_LPTIM_AutoReloadWriteCallback; /* Legacy weak Auto-reload register write complete Callback */
+ break;
+
+ case HAL_LPTIM_DIRECTION_UP_CB_ID :
+ hlptim->DirectionUpCallback = HAL_LPTIM_DirectionUpCallback; /* Legacy weak Up-counting direction change Callback */
+ break;
+
+ case HAL_LPTIM_DIRECTION_DOWN_CB_ID :
+ hlptim->DirectionDownCallback = HAL_LPTIM_DirectionDownCallback; /* Legacy weak Down-counting direction change Callback */
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hlptim->State == HAL_LPTIM_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_LPTIM_MSPINIT_CB_ID :
+ hlptim->MspInitCallback = HAL_LPTIM_MspInit; /* Legacy weak MspInit Callback */
+ break;
+
+ case HAL_LPTIM_MSPDEINIT_CB_ID :
+ hlptim->MspDeInitCallback = HAL_LPTIM_MspDeInit; /* Legacy weak Msp DeInit Callback */
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hlptim);
+
+ return status;
+}
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup LPTIM_Group5 Peripheral State functions
+ * @brief Peripheral State functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the LPTIM handle state.
+ * @param hlptim LPTIM handle
+ * @retval HAL state
+ */
+HAL_LPTIM_StateTypeDef HAL_LPTIM_GetState(LPTIM_HandleTypeDef *hlptim)
+{
+ /* Return LPTIM handle state */
+ return hlptim->State;
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup LPTIM_Private_Functions LPTIM Private Functions
+ * @{
+ */
+#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Reset interrupt callbacks to the legacy weak callbacks.
+ * @param lptim pointer to a LPTIM_HandleTypeDef structure that contains
+ * the configuration information for LPTIM module.
+ * @retval None
+ */
+static void LPTIM_ResetCallback(LPTIM_HandleTypeDef *lptim)
+{
+ /* Reset the LPTIM callback to the legacy weak callbacks */
+ lptim->CompareMatchCallback = HAL_LPTIM_CompareMatchCallback; /* Compare match Callback */
+ lptim->AutoReloadMatchCallback = HAL_LPTIM_AutoReloadMatchCallback; /* Auto-reload match Callback */
+ lptim->TriggerCallback = HAL_LPTIM_TriggerCallback; /* External trigger event detection Callback */
+ lptim->CompareWriteCallback = HAL_LPTIM_CompareWriteCallback; /* Compare register write complete Callback */
+ lptim->AutoReloadWriteCallback = HAL_LPTIM_AutoReloadWriteCallback; /* Auto-reload register write complete Callback */
+ lptim->DirectionUpCallback = HAL_LPTIM_DirectionUpCallback; /* Up-counting direction change Callback */
+ lptim->DirectionDownCallback = HAL_LPTIM_DirectionDownCallback; /* Down-counting direction change Callback */
+}
+#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
+
+/**
+ * @brief LPTimer Wait for flag set
+ * @param hlptim pointer to a LPTIM_HandleTypeDef structure that contains
+ * the configuration information for LPTIM module.
+ * @param flag The lptim flag
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef LPTIM_WaitForFlag(LPTIM_HandleTypeDef *hlptim, uint32_t flag)
+{
+ HAL_StatusTypeDef result = HAL_OK;
+ uint32_t count = TIMEOUT * (SystemCoreClock / 20UL / 1000UL);
+ do
+ {
+ count--;
+ if (count == 0UL)
+ {
+ result = HAL_TIMEOUT;
+ }
+ }
+ while ((!(__HAL_LPTIM_GET_FLAG((hlptim), (flag)))) && (count != 0UL));
+
+ return result;
+}
+
+/**
+ * @brief Disable LPTIM HW instance.
+ * @param hlptim pointer to a LPTIM_HandleTypeDef structure that contains
+ * the configuration information for LPTIM module.
+ * @note The following sequence is required to solve LPTIM disable HW limitation.
+ * Please check Errata Sheet ES0335 for more details under "MCU may remain
+ * stuck in LPTIM interrupt when entering Stop mode" section.
+ * @retval None
+ */
+void LPTIM_Disable(LPTIM_HandleTypeDef *hlptim)
+{
+ uint32_t tmpclksource = 0;
+ uint32_t tmpIER;
+ uint32_t tmpCFGR;
+ uint32_t tmpCMP;
+ uint32_t tmpARR;
+ uint32_t tmpCFGR2;
+
+ __disable_irq();
+
+ /*********** Save LPTIM Config ***********/
+ /* Save LPTIM source clock */
+ switch ((uint32_t)hlptim->Instance)
+ {
+ case LPTIM1_BASE:
+ tmpclksource = __HAL_RCC_GET_LPTIM1_SOURCE();
+ break;
+ case LPTIM2_BASE:
+ tmpclksource = __HAL_RCC_GET_LPTIM2_SOURCE();
+ break;
+#if defined(LPTIM3)
+ case LPTIM3_BASE:
+ tmpclksource = __HAL_RCC_GET_LPTIM3_SOURCE();
+ break;
+#endif /* LPTIM3 */
+#if defined(LPTIM4)
+ case LPTIM4_BASE:
+ tmpclksource = __HAL_RCC_GET_LPTIM4_SOURCE();
+ break;
+#endif /* LPTIM4 */
+#if defined(LPTIM5)
+ case LPTIM5_BASE:
+ tmpclksource = __HAL_RCC_GET_LPTIM5_SOURCE();
+ break;
+#endif /* LPTIM5 */
+ default:
+ break;
+ }
+
+ /* Save LPTIM configuration registers */
+ tmpIER = hlptim->Instance->IER;
+ tmpCFGR = hlptim->Instance->CFGR;
+ tmpCMP = hlptim->Instance->CMP;
+ tmpARR = hlptim->Instance->ARR;
+ tmpCFGR2 = hlptim->Instance->CFGR2;
+
+ /*********** Reset LPTIM ***********/
+ switch ((uint32_t)hlptim->Instance)
+ {
+ case LPTIM1_BASE:
+ __HAL_RCC_LPTIM1_FORCE_RESET();
+ __HAL_RCC_LPTIM1_RELEASE_RESET();
+ break;
+ case LPTIM2_BASE:
+ __HAL_RCC_LPTIM2_FORCE_RESET();
+ __HAL_RCC_LPTIM2_RELEASE_RESET();
+ break;
+#if defined(LPTIM3)
+ case LPTIM3_BASE:
+ __HAL_RCC_LPTIM3_FORCE_RESET();
+ __HAL_RCC_LPTIM3_RELEASE_RESET();
+ break;
+#endif /* LPTIM3 */
+#if defined(LPTIM4)
+ case LPTIM4_BASE:
+ __HAL_RCC_LPTIM4_FORCE_RESET();
+ __HAL_RCC_LPTIM4_RELEASE_RESET();
+ break;
+#endif /* LPTIM4 */
+#if defined(LPTIM5)
+ case LPTIM5_BASE:
+ __HAL_RCC_LPTIM5_FORCE_RESET();
+ __HAL_RCC_LPTIM5_RELEASE_RESET();
+ break;
+#endif /* LPTIM5 */
+ default:
+ break;
+ }
+
+ /*********** Restore LPTIM Config ***********/
+ if ((tmpCMP != 0UL) || (tmpARR != 0UL))
+ {
+ /* Force LPTIM source kernel clock from APB */
+ switch ((uint32_t)hlptim->Instance)
+ {
+ case LPTIM1_BASE:
+ __HAL_RCC_LPTIM1_CONFIG(RCC_LPTIM1CLKSOURCE_D2PCLK1);
+ break;
+ case LPTIM2_BASE:
+ __HAL_RCC_LPTIM2_CONFIG(RCC_LPTIM2CLKSOURCE_D3PCLK1);
+ break;
+#if defined(LPTIM3)
+ case LPTIM3_BASE:
+ __HAL_RCC_LPTIM3_CONFIG(RCC_LPTIM3CLKSOURCE_D3PCLK1);
+ break;
+#endif /* LPTIM3 */
+#if defined(LPTIM4)
+ case LPTIM4_BASE:
+ __HAL_RCC_LPTIM4_CONFIG(RCC_LPTIM4CLKSOURCE_D3PCLK1);
+ break;
+#endif /* LPTIM4 */
+#if defined(LPTIM5)
+ case LPTIM5_BASE:
+ __HAL_RCC_LPTIM5_CONFIG(RCC_LPTIM5CLKSOURCE_D3PCLK1);
+ break;
+#endif /* LPTIM5 */
+ default:
+ break;
+ }
+
+ if (tmpCMP != 0UL)
+ {
+ /* Restore CMP register (LPTIM should be enabled first) */
+ hlptim->Instance->CR |= LPTIM_CR_ENABLE;
+ hlptim->Instance->CMP = tmpCMP;
+
+ /* Wait for the completion of the write operation to the LPTIM_CMP register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT)
+ {
+ hlptim->State = HAL_LPTIM_STATE_TIMEOUT;
+ }
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
+ }
+
+ if (tmpARR != 0UL)
+ {
+ /* Restore ARR register (LPTIM should be enabled first) */
+ hlptim->Instance->CR |= LPTIM_CR_ENABLE;
+ hlptim->Instance->ARR = tmpARR;
+
+ /* Wait for the completion of the write operation to the LPTIM_ARR register */
+ if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT)
+ {
+ hlptim->State = HAL_LPTIM_STATE_TIMEOUT;
+ }
+
+ __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
+ }
+
+ /* Restore LPTIM source kernel clock */
+ switch ((uint32_t)hlptim->Instance)
+ {
+ case LPTIM1_BASE:
+ __HAL_RCC_LPTIM1_CONFIG(tmpclksource);
+ break;
+ case LPTIM2_BASE:
+ __HAL_RCC_LPTIM2_CONFIG(tmpclksource);
+ break;
+#if defined(LPTIM3)
+ case LPTIM3_BASE:
+ __HAL_RCC_LPTIM3_CONFIG(tmpclksource);
+ break;
+#endif /* LPTIM3 */
+#if defined(LPTIM4)
+ case LPTIM4_BASE:
+ __HAL_RCC_LPTIM4_CONFIG(tmpclksource);
+ break;
+#endif /* LPTIM4 */
+#if defined(LPTIM5)
+ case LPTIM5_BASE:
+ __HAL_RCC_LPTIM5_CONFIG(tmpclksource);
+ break;
+#endif /* LPTIM5 */
+ default:
+ break;
+ }
+ }
+
+ /* Restore configuration registers (LPTIM should be disabled first) */
+ hlptim->Instance->CR &= ~(LPTIM_CR_ENABLE);
+ hlptim->Instance->IER = tmpIER;
+ hlptim->Instance->CFGR = tmpCFGR;
+ hlptim->Instance->CFGR2 = tmpCFGR2;
+
+ __enable_irq();
+}
+/**
+ * @}
+ */
+#endif /* LPTIM1 || LPTIM2 || LPTIM3 || LPTIM4 || LPTIM5 */
+
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_ltdc.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_ltdc.c
new file mode 100644
index 0000000000..a3ddbeec46
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_ltdc.c
@@ -0,0 +1,2163 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_ltdc.c
+ * @author MCD Application Team
+ * @brief LTDC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the LTDC peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The LTDC HAL driver can be used as follows:
+
+ (#) Declare a LTDC_HandleTypeDef handle structure, for example: LTDC_HandleTypeDef hltdc;
+
+ (#) Initialize the LTDC low level resources by implementing the HAL_LTDC_MspInit() API:
+ (##) Enable the LTDC interface clock
+ (##) NVIC configuration if you need to use interrupt process
+ (+++) Configure the LTDC interrupt priority
+ (+++) Enable the NVIC LTDC IRQ Channel
+
+ (#) Initialize the required configuration through the following parameters:
+ the LTDC timing, the horizontal and vertical polarity, the pixel clock polarity,
+ Data Enable polarity and the LTDC background color value using HAL_LTDC_Init() function
+
+ *** Configuration ***
+ =========================
+ [..]
+ (#) Program the required configuration through the following parameters:
+ the pixel format, the blending factors, input alpha value, the window size
+ and the image size using HAL_LTDC_ConfigLayer() function for foreground
+ or/and background layer.
+
+ (#) Optionally, configure and enable the CLUT using HAL_LTDC_ConfigCLUT() and
+ HAL_LTDC_EnableCLUT functions.
+
+ (#) Optionally, enable the Dither using HAL_LTDC_EnableDither().
+
+ (#) Optionally, configure and enable the Color keying using HAL_LTDC_ConfigColorKeying()
+ and HAL_LTDC_EnableColorKeying functions.
+
+ (#) Optionally, configure LineInterrupt using HAL_LTDC_ProgramLineEvent()
+ function
+
+ (#) If needed, reconfigure and change the pixel format value, the alpha value
+ value, the window size, the window position and the layer start address
+ for foreground or/and background layer using respectively the following
+ functions: HAL_LTDC_SetPixelFormat(), HAL_LTDC_SetAlpha(), HAL_LTDC_SetWindowSize(),
+ HAL_LTDC_SetWindowPosition() and HAL_LTDC_SetAddress().
+
+ (#) Variant functions with _NoReload suffix allows to set the LTDC configuration/settings without immediate reload.
+ This is useful in case when the program requires to modify serval LTDC settings (on one or both layers)
+ then applying(reload) these settings in one shot by calling the function HAL_LTDC_Reload().
+
+ After calling the _NoReload functions to set different color/format/layer settings,
+ the program shall call the function HAL_LTDC_Reload() to apply(reload) these settings.
+ Function HAL_LTDC_Reload() can be called with the parameter ReloadType set to LTDC_RELOAD_IMMEDIATE if
+ an immediate reload is required.
+ Function HAL_LTDC_Reload() can be called with the parameter ReloadType set to LTDC_RELOAD_VERTICAL_BLANKING if
+ the reload should be done in the next vertical blanking period,
+ this option allows to avoid display flicker by applying the new settings during the vertical blanking period.
+
+
+ (#) To control LTDC state you can use the following function: HAL_LTDC_GetState()
+
+ *** LTDC HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in LTDC HAL driver.
+
+ (+) __HAL_LTDC_ENABLE: Enable the LTDC.
+ (+) __HAL_LTDC_DISABLE: Disable the LTDC.
+ (+) __HAL_LTDC_LAYER_ENABLE: Enable an LTDC Layer.
+ (+) __HAL_LTDC_LAYER_DISABLE: Disable an LTDC Layer.
+ (+) __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG: Reload Layer Configuration.
+ (+) __HAL_LTDC_GET_FLAG: Get the LTDC pending flags.
+ (+) __HAL_LTDC_CLEAR_FLAG: Clear the LTDC pending flags.
+ (+) __HAL_LTDC_ENABLE_IT: Enable the specified LTDC interrupts.
+ (+) __HAL_LTDC_DISABLE_IT: Disable the specified LTDC interrupts.
+ (+) __HAL_LTDC_GET_IT_SOURCE: Check whether the specified LTDC interrupt has occurred or not.
+
+ [..]
+ (@) You can refer to the LTDC HAL driver header file for more useful macros
+
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_LTDC_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use function HAL_LTDC_RegisterCallback() to register a callback.
+
+ [..]
+ Function HAL_LTDC_RegisterCallback() allows to register following callbacks:
+ (+) LineEventCallback : LTDC Line Event Callback.
+ (+) ReloadEventCallback : LTDC Reload Event Callback.
+ (+) ErrorCallback : LTDC Error Callback
+ (+) MspInitCallback : LTDC MspInit.
+ (+) MspDeInitCallback : LTDC MspDeInit.
+ [..]
+ This function takes as parameters the HAL peripheral handle, the callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function HAL_LTDC_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ HAL_LTDC_UnRegisterCallback() takes as parameters the HAL peripheral handle
+ and the callback ID.
+ [..]
+ This function allows to reset following callbacks:
+ (+) LineEventCallback : LTDC Line Event Callback
+ (+) ReloadEventCallback : LTDC Reload Event Callback
+ (+) ErrorCallback : LTDC Error Callback
+ (+) MspInitCallback : LTDC MspInit
+ (+) MspDeInitCallback : LTDC MspDeInit.
+
+ [..]
+ By default, after the HAL_LTDC_Init and when the state is HAL_LTDC_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples HAL_LTDC_LineEventCallback(), HAL_LTDC_ErrorCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak (surcharged) functions in the HAL_LTDC_Init() and HAL_LTDC_DeInit()
+ only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_LTDC_Init() and HAL_LTDC_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
+
+ [..]
+ Callbacks can be registered/unregistered in HAL_LTDC_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_LTDC_STATE_READY or HAL_LTDC_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_LTDC_RegisterCallback() before calling HAL_LTDC_DeInit()
+ or HAL_LTDC_Init() function.
+
+ [..]
+ When the compilation define USE_HAL_LTDC_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_LTDC_MODULE_ENABLED
+
+#if defined (LTDC)
+
+/** @defgroup LTDC LTDC
+ * @brief LTDC HAL module driver
+ * @{
+ */
+
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void LTDC_SetConfig(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx);
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup LTDC_Exported_Functions LTDC Exported Functions
+ * @{
+ */
+
+/** @defgroup LTDC_Exported_Functions_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the LTDC
+ (+) De-initialize the LTDC
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the LTDC according to the specified parameters in the LTDC_InitTypeDef.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_Init(LTDC_HandleTypeDef *hltdc)
+{
+ uint32_t tmp, tmp1;
+
+ /* Check the LTDC peripheral state */
+ if (hltdc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check function parameters */
+ assert_param(IS_LTDC_ALL_INSTANCE(hltdc->Instance));
+ assert_param(IS_LTDC_HSYNC(hltdc->Init.HorizontalSync));
+ assert_param(IS_LTDC_VSYNC(hltdc->Init.VerticalSync));
+ assert_param(IS_LTDC_AHBP(hltdc->Init.AccumulatedHBP));
+ assert_param(IS_LTDC_AVBP(hltdc->Init.AccumulatedVBP));
+ assert_param(IS_LTDC_AAH(hltdc->Init.AccumulatedActiveH));
+ assert_param(IS_LTDC_AAW(hltdc->Init.AccumulatedActiveW));
+ assert_param(IS_LTDC_TOTALH(hltdc->Init.TotalHeigh));
+ assert_param(IS_LTDC_TOTALW(hltdc->Init.TotalWidth));
+ assert_param(IS_LTDC_HSPOL(hltdc->Init.HSPolarity));
+ assert_param(IS_LTDC_VSPOL(hltdc->Init.VSPolarity));
+ assert_param(IS_LTDC_DEPOL(hltdc->Init.DEPolarity));
+ assert_param(IS_LTDC_PCPOL(hltdc->Init.PCPolarity));
+
+#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
+ if (hltdc->State == HAL_LTDC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hltdc->Lock = HAL_UNLOCKED;
+
+ /* Reset the LTDC callback to the legacy weak callbacks */
+ hltdc->LineEventCallback = HAL_LTDC_LineEventCallback; /* Legacy weak LineEventCallback */
+ hltdc->ReloadEventCallback = HAL_LTDC_ReloadEventCallback; /* Legacy weak ReloadEventCallback */
+ hltdc->ErrorCallback = HAL_LTDC_ErrorCallback; /* Legacy weak ErrorCallback */
+
+ if (hltdc->MspInitCallback == NULL)
+ {
+ hltdc->MspInitCallback = HAL_LTDC_MspInit;
+ }
+ /* Init the low level hardware */
+ hltdc->MspInitCallback(hltdc);
+ }
+#else
+ if (hltdc->State == HAL_LTDC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hltdc->Lock = HAL_UNLOCKED;
+ /* Init the low level hardware */
+ HAL_LTDC_MspInit(hltdc);
+ }
+#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Configure the HS, VS, DE and PC polarity */
+ hltdc->Instance->GCR &= ~(LTDC_GCR_HSPOL | LTDC_GCR_VSPOL | LTDC_GCR_DEPOL | LTDC_GCR_PCPOL);
+ hltdc->Instance->GCR |= (uint32_t)(hltdc->Init.HSPolarity | hltdc->Init.VSPolarity | \
+ hltdc->Init.DEPolarity | hltdc->Init.PCPolarity);
+
+ /* Set Synchronization size */
+ hltdc->Instance->SSCR &= ~(LTDC_SSCR_VSH | LTDC_SSCR_HSW);
+ tmp = (hltdc->Init.HorizontalSync << 16U);
+ hltdc->Instance->SSCR |= (tmp | hltdc->Init.VerticalSync);
+
+ /* Set Accumulated Back porch */
+ hltdc->Instance->BPCR &= ~(LTDC_BPCR_AVBP | LTDC_BPCR_AHBP);
+ tmp = (hltdc->Init.AccumulatedHBP << 16U);
+ hltdc->Instance->BPCR |= (tmp | hltdc->Init.AccumulatedVBP);
+
+ /* Set Accumulated Active Width */
+ hltdc->Instance->AWCR &= ~(LTDC_AWCR_AAH | LTDC_AWCR_AAW);
+ tmp = (hltdc->Init.AccumulatedActiveW << 16U);
+ hltdc->Instance->AWCR |= (tmp | hltdc->Init.AccumulatedActiveH);
+
+ /* Set Total Width */
+ hltdc->Instance->TWCR &= ~(LTDC_TWCR_TOTALH | LTDC_TWCR_TOTALW);
+ tmp = (hltdc->Init.TotalWidth << 16U);
+ hltdc->Instance->TWCR |= (tmp | hltdc->Init.TotalHeigh);
+
+ /* Set the background color value */
+ tmp = ((uint32_t)(hltdc->Init.Backcolor.Green) << 8U);
+ tmp1 = ((uint32_t)(hltdc->Init.Backcolor.Red) << 16U);
+ hltdc->Instance->BCCR &= ~(LTDC_BCCR_BCBLUE | LTDC_BCCR_BCGREEN | LTDC_BCCR_BCRED);
+ hltdc->Instance->BCCR |= (tmp1 | tmp | hltdc->Init.Backcolor.Blue);
+
+ /* Enable the Transfer Error and FIFO underrun interrupts */
+ __HAL_LTDC_ENABLE_IT(hltdc, LTDC_IT_TE | LTDC_IT_FU);
+
+ /* Enable LTDC by setting LTDCEN bit */
+ __HAL_LTDC_ENABLE(hltdc);
+
+ /* Initialize the error code */
+ hltdc->ErrorCode = HAL_LTDC_ERROR_NONE;
+
+ /* Initialize the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief De-initialize the LTDC peripheral.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval None
+ */
+
+HAL_StatusTypeDef HAL_LTDC_DeInit(LTDC_HandleTypeDef *hltdc)
+{
+#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
+ if (hltdc->MspDeInitCallback == NULL)
+ {
+ hltdc->MspDeInitCallback = HAL_LTDC_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ hltdc->MspDeInitCallback(hltdc);
+#else
+ /* DeInit the low level hardware */
+ HAL_LTDC_MspDeInit(hltdc);
+#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */
+
+ /* Initialize the error code */
+ hltdc->ErrorCode = HAL_LTDC_ERROR_NONE;
+
+ /* Initialize the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the LTDC MSP.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval None
+ */
+__weak void HAL_LTDC_MspInit(LTDC_HandleTypeDef *hltdc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hltdc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LTDC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief De-initialize the LTDC MSP.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval None
+ */
+__weak void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef *hltdc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hltdc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LTDC_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User LTDC Callback
+ * To be used instead of the weak predefined callback
+ * @param hltdc ltdc handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_LTDC_LINE_EVENT_CB_ID Line Event Callback ID
+ * @arg @ref HAL_LTDC_RELOAD_EVENT_CB_ID Reload Event Callback ID
+ * @arg @ref HAL_LTDC_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_LTDC_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_LTDC_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_LTDC_RegisterCallback(LTDC_HandleTypeDef *hltdc, HAL_LTDC_CallbackIDTypeDef CallbackID, pLTDC_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ if (hltdc->State == HAL_LTDC_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_LTDC_LINE_EVENT_CB_ID :
+ hltdc->LineEventCallback = pCallback;
+ break;
+
+ case HAL_LTDC_RELOAD_EVENT_CB_ID :
+ hltdc->ReloadEventCallback = pCallback;
+ break;
+
+ case HAL_LTDC_ERROR_CB_ID :
+ hltdc->ErrorCallback = pCallback;
+ break;
+
+ case HAL_LTDC_MSPINIT_CB_ID :
+ hltdc->MspInitCallback = pCallback;
+ break;
+
+ case HAL_LTDC_MSPDEINIT_CB_ID :
+ hltdc->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hltdc->State == HAL_LTDC_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_LTDC_MSPINIT_CB_ID :
+ hltdc->MspInitCallback = pCallback;
+ break;
+
+ case HAL_LTDC_MSPDEINIT_CB_ID :
+ hltdc->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hltdc);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an LTDC Callback
+ * LTDC callabck is redirected to the weak predefined callback
+ * @param hltdc ltdc handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_LTDC_LINE_EVENT_CB_ID Line Event Callback ID
+ * @arg @ref HAL_LTDC_RELOAD_EVENT_CB_ID Reload Event Callback ID
+ * @arg @ref HAL_LTDC_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_LTDC_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_LTDC_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_LTDC_UnRegisterCallback(LTDC_HandleTypeDef *hltdc, HAL_LTDC_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ if (hltdc->State == HAL_LTDC_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_LTDC_LINE_EVENT_CB_ID :
+ hltdc->LineEventCallback = HAL_LTDC_LineEventCallback; /* Legacy weak LineEventCallback */
+ break;
+
+ case HAL_LTDC_RELOAD_EVENT_CB_ID :
+ hltdc->ReloadEventCallback = HAL_LTDC_ReloadEventCallback; /* Legacy weak ReloadEventCallback */
+ break;
+
+ case HAL_LTDC_ERROR_CB_ID :
+ hltdc->ErrorCallback = HAL_LTDC_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_LTDC_MSPINIT_CB_ID :
+ hltdc->MspInitCallback = HAL_LTDC_MspInit; /* Legcay weak MspInit Callback */
+ break;
+
+ case HAL_LTDC_MSPDEINIT_CB_ID :
+ hltdc->MspDeInitCallback = HAL_LTDC_MspDeInit; /* Legcay weak MspDeInit Callback */
+ break;
+
+ default :
+ /* Update the error code */
+ hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hltdc->State == HAL_LTDC_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_LTDC_MSPINIT_CB_ID :
+ hltdc->MspInitCallback = HAL_LTDC_MspInit; /* Legcay weak MspInit Callback */
+ break;
+
+ case HAL_LTDC_MSPDEINIT_CB_ID :
+ hltdc->MspDeInitCallback = HAL_LTDC_MspDeInit; /* Legcay weak MspDeInit Callback */
+ break;
+
+ default :
+ /* Update the error code */
+ hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hltdc);
+
+ return status;
+}
+#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup LTDC_Exported_Functions_Group2 IO operation functions
+ * @brief IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides function allowing to:
+ (+) Handle LTDC interrupt request
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Handle LTDC interrupt request.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval HAL status
+ */
+void HAL_LTDC_IRQHandler(LTDC_HandleTypeDef *hltdc)
+{
+ uint32_t isrflags = READ_REG(hltdc->Instance->ISR);
+ uint32_t itsources = READ_REG(hltdc->Instance->IER);
+
+ /* Transfer Error Interrupt management ***************************************/
+ if (((isrflags & LTDC_ISR_TERRIF) != 0U) && ((itsources & LTDC_IER_TERRIE) != 0U))
+ {
+ /* Disable the transfer Error interrupt */
+ __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_TE);
+
+ /* Clear the transfer error flag */
+ __HAL_LTDC_CLEAR_FLAG(hltdc, LTDC_FLAG_TE);
+
+ /* Update error code */
+ hltdc->ErrorCode |= HAL_LTDC_ERROR_TE;
+
+ /* Change LTDC state */
+ hltdc->State = HAL_LTDC_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ /* Transfer error Callback */
+#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hltdc->ErrorCallback(hltdc);
+#else
+ /* Call legacy error callback*/
+ HAL_LTDC_ErrorCallback(hltdc);
+#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */
+ }
+
+ /* FIFO underrun Interrupt management ***************************************/
+ if (((isrflags & LTDC_ISR_FUIF) != 0U) && ((itsources & LTDC_IER_FUIE) != 0U))
+ {
+ /* Disable the FIFO underrun interrupt */
+ __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_FU);
+
+ /* Clear the FIFO underrun flag */
+ __HAL_LTDC_CLEAR_FLAG(hltdc, LTDC_FLAG_FU);
+
+ /* Update error code */
+ hltdc->ErrorCode |= HAL_LTDC_ERROR_FU;
+
+ /* Change LTDC state */
+ hltdc->State = HAL_LTDC_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ /* Transfer error Callback */
+#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ hltdc->ErrorCallback(hltdc);
+#else
+ /* Call legacy error callback*/
+ HAL_LTDC_ErrorCallback(hltdc);
+#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */
+ }
+
+ /* Line Interrupt management ************************************************/
+ if (((isrflags & LTDC_ISR_LIF) != 0U) && ((itsources & LTDC_IER_LIE) != 0U))
+ {
+ /* Disable the Line interrupt */
+ __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_LI);
+
+ /* Clear the Line interrupt flag */
+ __HAL_LTDC_CLEAR_FLAG(hltdc, LTDC_FLAG_LI);
+
+ /* Change LTDC state */
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ /* Line interrupt Callback */
+#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
+ /*Call registered Line Event callback */
+ hltdc->LineEventCallback(hltdc);
+#else
+ /*Call Legacy Line Event callback */
+ HAL_LTDC_LineEventCallback(hltdc);
+#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */
+ }
+
+ /* Register reload Interrupt management ***************************************/
+ if (((isrflags & LTDC_ISR_RRIF) != 0U) && ((itsources & LTDC_IER_RRIE) != 0U))
+ {
+ /* Disable the register reload interrupt */
+ __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_RR);
+
+ /* Clear the register reload flag */
+ __HAL_LTDC_CLEAR_FLAG(hltdc, LTDC_FLAG_RR);
+
+ /* Change LTDC state */
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ /* Reload interrupt Callback */
+#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
+ /*Call registered reload Event callback */
+ hltdc->ReloadEventCallback(hltdc);
+#else
+ /*Call Legacy Reload Event callback */
+ HAL_LTDC_ReloadEventCallback(hltdc);
+#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Error LTDC callback.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval None
+ */
+__weak void HAL_LTDC_ErrorCallback(LTDC_HandleTypeDef *hltdc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hltdc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LTDC_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Line Event callback.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval None
+ */
+__weak void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hltdc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LTDC_LineEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Reload Event callback.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval None
+ */
+__weak void HAL_LTDC_ReloadEventCallback(LTDC_HandleTypeDef *hltdc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hltdc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_LTDC_ReloadEvenCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup LTDC_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure the LTDC foreground or/and background parameters.
+ (+) Set the active layer.
+ (+) Configure the color keying.
+ (+) Configure the C-LUT.
+ (+) Enable / Disable the color keying.
+ (+) Enable / Disable the C-LUT.
+ (+) Update the layer position.
+ (+) Update the layer size.
+ (+) Update pixel format on the fly.
+ (+) Update transparency on the fly.
+ (+) Update address on the fly.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the LTDC Layer according to the specified
+ * parameters in the LTDC_InitTypeDef and create the associated handle.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param pLayerCfg pointer to a LTDC_LayerCfgTypeDef structure that contains
+ * the configuration information for the Layer.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_ConfigLayer(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+ assert_param(IS_LTDC_HCONFIGST(pLayerCfg->WindowX0));
+ assert_param(IS_LTDC_HCONFIGSP(pLayerCfg->WindowX1));
+ assert_param(IS_LTDC_VCONFIGST(pLayerCfg->WindowY0));
+ assert_param(IS_LTDC_VCONFIGSP(pLayerCfg->WindowY1));
+ assert_param(IS_LTDC_PIXEL_FORMAT(pLayerCfg->PixelFormat));
+ assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha));
+ assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha0));
+ assert_param(IS_LTDC_BLENDING_FACTOR1(pLayerCfg->BlendingFactor1));
+ assert_param(IS_LTDC_BLENDING_FACTOR2(pLayerCfg->BlendingFactor2));
+ assert_param(IS_LTDC_CFBLL(pLayerCfg->ImageWidth));
+ assert_param(IS_LTDC_CFBLNBR(pLayerCfg->ImageHeight));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Copy new layer configuration into handle structure */
+ hltdc->LayerCfg[LayerIdx] = *pLayerCfg;
+
+ /* Configure the LTDC Layer */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Initialize the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the color keying.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param RGBValue the color key value
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_ConfigColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t RGBValue, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Configure the default color values */
+ LTDC_LAYER(hltdc, LayerIdx)->CKCR &= ~(LTDC_LxCKCR_CKBLUE | LTDC_LxCKCR_CKGREEN | LTDC_LxCKCR_CKRED);
+ LTDC_LAYER(hltdc, LayerIdx)->CKCR = RGBValue;
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Load the color lookup table.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param pCLUT pointer to the color lookup table address.
+ * @param CLUTSize the color lookup table size.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_ConfigCLUT(LTDC_HandleTypeDef *hltdc, uint32_t *pCLUT, uint32_t CLUTSize, uint32_t LayerIdx)
+{
+ uint32_t tmp;
+ uint32_t counter;
+ uint32_t *pcolorlut = pCLUT;
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ for (counter = 0U; (counter < CLUTSize); counter++)
+ {
+ if (hltdc->LayerCfg[LayerIdx].PixelFormat == LTDC_PIXEL_FORMAT_AL44)
+ {
+ tmp = (((counter + (16U*counter)) << 24U) | ((uint32_t)(*pcolorlut) & 0xFFU) | ((uint32_t)(*pcolorlut) & 0xFF00U) | ((uint32_t)(*pcolorlut) & 0xFF0000U));
+ }
+ else
+ {
+ tmp = ((counter << 24U) | ((uint32_t)(*pcolorlut) & 0xFFU) | ((uint32_t)(*pcolorlut) & 0xFF00U) | ((uint32_t)(*pcolorlut) & 0xFF0000U));
+ }
+
+ pcolorlut++;
+
+ /* Specifies the C-LUT address and RGB value */
+ LTDC_LAYER(hltdc, LayerIdx)->CLUTWR = tmp;
+ }
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the color keying.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_EnableColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Enable LTDC color keying by setting COLKEN bit */
+ LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_COLKEN;
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the color keying.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_DisableColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Disable LTDC color keying by setting COLKEN bit */
+ LTDC_LAYER(hltdc, LayerIdx)->CR &= ~(uint32_t)LTDC_LxCR_COLKEN;
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the color lookup table.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_EnableCLUT(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Enable LTDC color lookup table by setting CLUTEN bit */
+ LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_CLUTEN;
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the color lookup table.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_DisableCLUT(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Disable LTDC color lookup table by setting CLUTEN bit */
+ LTDC_LAYER(hltdc, LayerIdx)->CR &= ~(uint32_t)LTDC_LxCR_CLUTEN;
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable Dither.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_LTDC_EnableDither(LTDC_HandleTypeDef *hltdc)
+{
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Enable Dither by setting DTEN bit */
+ LTDC->GCR |= (uint32_t)LTDC_GCR_DEN;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable Dither.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_LTDC_DisableDither(LTDC_HandleTypeDef *hltdc)
+{
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Disable Dither by setting DTEN bit */
+ LTDC->GCR &= ~(uint32_t)LTDC_GCR_DEN;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the LTDC window size.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param XSize LTDC Pixel per line
+ * @param YSize LTDC Line number
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetWindowSize(LTDC_HandleTypeDef *hltdc, uint32_t XSize, uint32_t YSize, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters (Layers parameters)*/
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+ assert_param(IS_LTDC_CFBLL(XSize));
+ assert_param(IS_LTDC_CFBLNBR(YSize));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* update horizontal stop */
+ pLayerCfg->WindowX1 = XSize + pLayerCfg->WindowX0;
+
+ /* update vertical stop */
+ pLayerCfg->WindowY1 = YSize + pLayerCfg->WindowY0;
+
+ /* Reconfigures the color frame buffer pitch in byte */
+ pLayerCfg->ImageWidth = XSize;
+
+ /* Reconfigures the frame buffer line number */
+ pLayerCfg->ImageHeight = YSize;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the LTDC window position.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param X0 LTDC window X offset
+ * @param Y0 LTDC window Y offset
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetWindowPosition(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+ assert_param(IS_LTDC_CFBLL(X0));
+ assert_param(IS_LTDC_CFBLNBR(Y0));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* update horizontal start/stop */
+ pLayerCfg->WindowX0 = X0;
+ pLayerCfg->WindowX1 = X0 + pLayerCfg->ImageWidth;
+
+ /* update vertical start/stop */
+ pLayerCfg->WindowY0 = Y0;
+ pLayerCfg->WindowY1 = Y0 + pLayerCfg->ImageHeight;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reconfigure the pixel format.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param Pixelformat new pixel format value.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetPixelFormat(LTDC_HandleTypeDef *hltdc, uint32_t Pixelformat, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_PIXEL_FORMAT(Pixelformat));
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* Reconfigure the pixel format */
+ pLayerCfg->PixelFormat = Pixelformat;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reconfigure the layer alpha value.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param Alpha new alpha value.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetAlpha(LTDC_HandleTypeDef *hltdc, uint32_t Alpha, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_ALPHA(Alpha));
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* Reconfigure the Alpha value */
+ pLayerCfg->Alpha = Alpha;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+/**
+ * @brief Reconfigure the frame buffer Address.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param Address new address value.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetAddress(LTDC_HandleTypeDef *hltdc, uint32_t Address, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* Reconfigure the Address */
+ pLayerCfg->FBStartAdress = Address;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Set the Immediate Reload type */
+ hltdc->Instance->SRCR = LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Function used to reconfigure the pitch for specific cases where the attached LayerIdx buffer have a width that is
+ * larger than the one intended to be displayed on screen. Example of a buffer 800x480 attached to layer for which we
+ * want to read and display on screen only a portion 320x240 taken in the center of the buffer. The pitch in pixels
+ * will be in that case 800 pixels and not 320 pixels as initially configured by previous call to HAL_LTDC_ConfigLayer().
+ * @note This function should be called only after a previous call to HAL_LTDC_ConfigLayer() to modify the default pitch
+ * configured by HAL_LTDC_ConfigLayer() when required (refer to example described just above).
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LinePitchInPixels New line pitch in pixels to configure for LTDC layer 'LayerIdx'.
+ * @param LayerIdx LTDC layer index concerned by the modification of line pitch.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetPitch(LTDC_HandleTypeDef *hltdc, uint32_t LinePitchInPixels, uint32_t LayerIdx)
+{
+ uint32_t tmp;
+ uint32_t pitchUpdate;
+ uint32_t pixelFormat;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* get LayerIdx used pixel format */
+ pixelFormat = hltdc->LayerCfg[LayerIdx].PixelFormat;
+
+ if (pixelFormat == LTDC_PIXEL_FORMAT_ARGB8888)
+ {
+ tmp = 4U;
+ }
+ else if (pixelFormat == LTDC_PIXEL_FORMAT_RGB888)
+ {
+ tmp = 3U;
+ }
+ else if ((pixelFormat == LTDC_PIXEL_FORMAT_ARGB4444) || \
+ (pixelFormat == LTDC_PIXEL_FORMAT_RGB565) || \
+ (pixelFormat == LTDC_PIXEL_FORMAT_ARGB1555) || \
+ (pixelFormat == LTDC_PIXEL_FORMAT_AL88))
+ {
+ tmp = 2U;
+ }
+ else
+ {
+ tmp = 1U;
+ }
+
+ pitchUpdate = ((LinePitchInPixels * tmp) << 16U);
+
+ /* Clear previously set standard pitch */
+ LTDC_LAYER(hltdc, LayerIdx)->CFBLR &= ~LTDC_LxCFBLR_CFBP;
+
+ /* Set the Reload type as immediate update of LTDC pitch configured above */
+ LTDC->SRCR |= LTDC_SRCR_IMR;
+
+ /* Set new line pitch value */
+ LTDC_LAYER(hltdc, LayerIdx)->CFBLR |= pitchUpdate;
+
+ /* Set the Reload type as immediate update of LTDC pitch configured above */
+ LTDC->SRCR |= LTDC_SRCR_IMR;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Define the position of the line interrupt.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param Line Line Interrupt Position.
+ * @note User application may resort to HAL_LTDC_LineEventCallback() at line interrupt generation.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_ProgramLineEvent(LTDC_HandleTypeDef *hltdc, uint32_t Line)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LIPOS(Line));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Disable the Line interrupt */
+ __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_LI);
+
+ /* Set the Line Interrupt position */
+ LTDC->LIPCR = (uint32_t)Line;
+
+ /* Enable the Line interrupt */
+ __HAL_LTDC_ENABLE_IT(hltdc, LTDC_IT_LI);
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reload LTDC Layers configuration.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param ReloadType This parameter can be one of the following values :
+ * LTDC_RELOAD_IMMEDIATE : Immediate Reload
+ * LTDC_RELOAD_VERTICAL_BLANKING : Reload in the next Vertical Blanking
+ * @note User application may resort to HAL_LTDC_ReloadEventCallback() at reload interrupt generation.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_Reload(LTDC_HandleTypeDef *hltdc, uint32_t ReloadType)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_RELOAD(ReloadType));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Enable the Reload interrupt */
+ __HAL_LTDC_ENABLE_IT(hltdc, LTDC_IT_RR);
+
+ /* Apply Reload type */
+ hltdc->Instance->SRCR = ReloadType;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the LTDC Layer according to the specified without reloading
+ * parameters in the LTDC_InitTypeDef and create the associated handle.
+ * Variant of the function HAL_LTDC_ConfigLayer without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param pLayerCfg pointer to a LTDC_LayerCfgTypeDef structure that contains
+ * the configuration information for the Layer.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_ConfigLayer_NoReload(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+ assert_param(IS_LTDC_HCONFIGST(pLayerCfg->WindowX0));
+ assert_param(IS_LTDC_HCONFIGSP(pLayerCfg->WindowX1));
+ assert_param(IS_LTDC_VCONFIGST(pLayerCfg->WindowY0));
+ assert_param(IS_LTDC_VCONFIGSP(pLayerCfg->WindowY1));
+ assert_param(IS_LTDC_PIXEL_FORMAT(pLayerCfg->PixelFormat));
+ assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha));
+ assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha0));
+ assert_param(IS_LTDC_BLENDING_FACTOR1(pLayerCfg->BlendingFactor1));
+ assert_param(IS_LTDC_BLENDING_FACTOR2(pLayerCfg->BlendingFactor2));
+ assert_param(IS_LTDC_CFBLL(pLayerCfg->ImageWidth));
+ assert_param(IS_LTDC_CFBLNBR(pLayerCfg->ImageHeight));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Copy new layer configuration into handle structure */
+ hltdc->LayerCfg[LayerIdx] = *pLayerCfg;
+
+ /* Configure the LTDC Layer */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Initialize the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the LTDC window size without reloading.
+ * Variant of the function HAL_LTDC_SetWindowSize without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param XSize LTDC Pixel per line
+ * @param YSize LTDC Line number
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetWindowSize_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t XSize, uint32_t YSize, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters (Layers parameters)*/
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+ assert_param(IS_LTDC_CFBLL(XSize));
+ assert_param(IS_LTDC_CFBLNBR(YSize));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* update horizontal stop */
+ pLayerCfg->WindowX1 = XSize + pLayerCfg->WindowX0;
+
+ /* update vertical stop */
+ pLayerCfg->WindowY1 = YSize + pLayerCfg->WindowY0;
+
+ /* Reconfigures the color frame buffer pitch in byte */
+ pLayerCfg->ImageWidth = XSize;
+
+ /* Reconfigures the frame buffer line number */
+ pLayerCfg->ImageHeight = YSize;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the LTDC window position without reloading.
+ * Variant of the function HAL_LTDC_SetWindowPosition without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param X0 LTDC window X offset
+ * @param Y0 LTDC window Y offset
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetWindowPosition_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+ assert_param(IS_LTDC_CFBLL(X0));
+ assert_param(IS_LTDC_CFBLNBR(Y0));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* update horizontal start/stop */
+ pLayerCfg->WindowX0 = X0;
+ pLayerCfg->WindowX1 = X0 + pLayerCfg->ImageWidth;
+
+ /* update vertical start/stop */
+ pLayerCfg->WindowY0 = Y0;
+ pLayerCfg->WindowY1 = Y0 + pLayerCfg->ImageHeight;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reconfigure the pixel format without reloading.
+ * Variant of the function HAL_LTDC_SetPixelFormat without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDfef structure that contains
+ * the configuration information for the LTDC.
+ * @param Pixelformat new pixel format value.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetPixelFormat_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Pixelformat, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_PIXEL_FORMAT(Pixelformat));
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* Reconfigure the pixel format */
+ pLayerCfg->PixelFormat = Pixelformat;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reconfigure the layer alpha value without reloading.
+ * Variant of the function HAL_LTDC_SetAlpha without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param Alpha new alpha value.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetAlpha_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Alpha, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_ALPHA(Alpha));
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* Reconfigure the Alpha value */
+ pLayerCfg->Alpha = Alpha;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reconfigure the frame buffer Address without reloading.
+ * Variant of the function HAL_LTDC_SetAddress without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param Address new address value.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetAddress_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Address, uint32_t LayerIdx)
+{
+ LTDC_LayerCfgTypeDef *pLayerCfg;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Get layer configuration from handle structure */
+ pLayerCfg = &hltdc->LayerCfg[LayerIdx];
+
+ /* Reconfigure the Address */
+ pLayerCfg->FBStartAdress = Address;
+
+ /* Set LTDC parameters */
+ LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Function used to reconfigure the pitch for specific cases where the attached LayerIdx buffer have a width that is
+ * larger than the one intended to be displayed on screen. Example of a buffer 800x480 attached to layer for which we
+ * want to read and display on screen only a portion 320x240 taken in the center of the buffer. The pitch in pixels
+ * will be in that case 800 pixels and not 320 pixels as initially configured by previous call to HAL_LTDC_ConfigLayer().
+ * @note This function should be called only after a previous call to HAL_LTDC_ConfigLayer() to modify the default pitch
+ * configured by HAL_LTDC_ConfigLayer() when required (refer to example described just above).
+ * Variant of the function HAL_LTDC_SetPitch without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LinePitchInPixels New line pitch in pixels to configure for LTDC layer 'LayerIdx'.
+ * @param LayerIdx LTDC layer index concerned by the modification of line pitch.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_SetPitch_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LinePitchInPixels, uint32_t LayerIdx)
+{
+ uint32_t tmp;
+ uint32_t pitchUpdate;
+ uint32_t pixelFormat;
+
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* get LayerIdx used pixel format */
+ pixelFormat = hltdc->LayerCfg[LayerIdx].PixelFormat;
+
+ if (pixelFormat == LTDC_PIXEL_FORMAT_ARGB8888)
+ {
+ tmp = 4U;
+ }
+ else if (pixelFormat == LTDC_PIXEL_FORMAT_RGB888)
+ {
+ tmp = 3U;
+ }
+ else if ((pixelFormat == LTDC_PIXEL_FORMAT_ARGB4444) || \
+ (pixelFormat == LTDC_PIXEL_FORMAT_RGB565) || \
+ (pixelFormat == LTDC_PIXEL_FORMAT_ARGB1555) || \
+ (pixelFormat == LTDC_PIXEL_FORMAT_AL88))
+ {
+ tmp = 2U;
+ }
+ else
+ {
+ tmp = 1U;
+ }
+
+ pitchUpdate = ((LinePitchInPixels * tmp) << 16U);
+
+ /* Clear previously set standard pitch */
+ LTDC_LAYER(hltdc, LayerIdx)->CFBLR &= ~LTDC_LxCFBLR_CFBP;
+
+ /* Set new line pitch value */
+ LTDC_LAYER(hltdc, LayerIdx)->CFBLR |= pitchUpdate;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Configure the color keying without reloading.
+ * Variant of the function HAL_LTDC_ConfigColorKeying without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param RGBValue the color key value
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_ConfigColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t RGBValue, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Configure the default color values */
+ LTDC_LAYER(hltdc, LayerIdx)->CKCR &= ~(LTDC_LxCKCR_CKBLUE | LTDC_LxCKCR_CKGREEN | LTDC_LxCKCR_CKRED);
+ LTDC_LAYER(hltdc, LayerIdx)->CKCR = RGBValue;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the color keying without reloading.
+ * Variant of the function HAL_LTDC_EnableColorKeying without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_EnableColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Enable LTDC color keying by setting COLKEN bit */
+ LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_COLKEN;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the color keying without reloading.
+ * Variant of the function HAL_LTDC_DisableColorKeying without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_DisableColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Disable LTDC color keying by setting COLKEN bit */
+ LTDC_LAYER(hltdc, LayerIdx)->CR &= ~(uint32_t)LTDC_LxCR_COLKEN;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the color lookup table without reloading.
+ * Variant of the function HAL_LTDC_EnableCLUT without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_EnableCLUT_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Disable LTDC color lookup table by setting CLUTEN bit */
+ LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_CLUTEN;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the color lookup table without reloading.
+ * Variant of the function HAL_LTDC_DisableCLUT without immediate reload.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values:
+ * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDC_DisableCLUT_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LTDC_LAYER(LayerIdx));
+
+ /* Process locked */
+ __HAL_LOCK(hltdc);
+
+ /* Change LTDC peripheral state */
+ hltdc->State = HAL_LTDC_STATE_BUSY;
+
+ /* Disable LTDC color lookup table by setting CLUTEN bit */
+ LTDC_LAYER(hltdc, LayerIdx)->CR &= ~(uint32_t)LTDC_LxCR_CLUTEN;
+
+ /* Change the LTDC state*/
+ hltdc->State = HAL_LTDC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hltdc);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup LTDC_Exported_Functions_Group4 Peripheral State and Errors functions
+ * @brief Peripheral State and Errors functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Check the LTDC handle state.
+ (+) Get the LTDC handle error code.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the LTDC handle state.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval HAL state
+ */
+HAL_LTDC_StateTypeDef HAL_LTDC_GetState(LTDC_HandleTypeDef *hltdc)
+{
+ return hltdc->State;
+}
+
+/**
+ * @brief Return the LTDC handle error code.
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @retval LTDC Error Code
+ */
+uint32_t HAL_LTDC_GetError(LTDC_HandleTypeDef *hltdc)
+{
+ return hltdc->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup LTDC_Private_Functions LTDC Private Functions
+ * @{
+ */
+
+/**
+ * @brief Configure the LTDC peripheral
+ * @param hltdc Pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param pLayerCfg Pointer LTDC Layer Configuration structure
+ * @param LayerIdx LTDC Layer index.
+ * This parameter can be one of the following values: LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1)
+ * @retval None
+ */
+static void LTDC_SetConfig(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx)
+{
+ uint32_t tmp;
+ uint32_t tmp1;
+ uint32_t tmp2;
+
+ /* Configure the horizontal start and stop position */
+ tmp = ((pLayerCfg->WindowX1 + ((hltdc->Instance->BPCR & LTDC_BPCR_AHBP) >> 16U)) << 16U);
+ LTDC_LAYER(hltdc, LayerIdx)->WHPCR &= ~(LTDC_LxWHPCR_WHSTPOS | LTDC_LxWHPCR_WHSPPOS);
+ LTDC_LAYER(hltdc, LayerIdx)->WHPCR = ((pLayerCfg->WindowX0 + ((hltdc->Instance->BPCR & LTDC_BPCR_AHBP) >> 16U) + 1U) | tmp);
+
+ /* Configure the vertical start and stop position */
+ tmp = ((pLayerCfg->WindowY1 + (hltdc->Instance->BPCR & LTDC_BPCR_AVBP)) << 16U);
+ LTDC_LAYER(hltdc, LayerIdx)->WVPCR &= ~(LTDC_LxWVPCR_WVSTPOS | LTDC_LxWVPCR_WVSPPOS);
+ LTDC_LAYER(hltdc, LayerIdx)->WVPCR = ((pLayerCfg->WindowY0 + (hltdc->Instance->BPCR & LTDC_BPCR_AVBP) + 1U) | tmp);
+
+ /* Specifies the pixel format */
+ LTDC_LAYER(hltdc, LayerIdx)->PFCR &= ~(LTDC_LxPFCR_PF);
+ LTDC_LAYER(hltdc, LayerIdx)->PFCR = (pLayerCfg->PixelFormat);
+
+ /* Configure the default color values */
+ tmp = ((uint32_t)(pLayerCfg->Backcolor.Green) << 8U);
+ tmp1 = ((uint32_t)(pLayerCfg->Backcolor.Red) << 16U);
+ tmp2 = (pLayerCfg->Alpha0 << 24U);
+ LTDC_LAYER(hltdc, LayerIdx)->DCCR &= ~(LTDC_LxDCCR_DCBLUE | LTDC_LxDCCR_DCGREEN | LTDC_LxDCCR_DCRED | LTDC_LxDCCR_DCALPHA);
+ LTDC_LAYER(hltdc, LayerIdx)->DCCR = (pLayerCfg->Backcolor.Blue | tmp | tmp1 | tmp2);
+
+ /* Specifies the constant alpha value */
+ LTDC_LAYER(hltdc, LayerIdx)->CACR &= ~(LTDC_LxCACR_CONSTA);
+ LTDC_LAYER(hltdc, LayerIdx)->CACR = (pLayerCfg->Alpha);
+
+ /* Specifies the blending factors */
+ LTDC_LAYER(hltdc, LayerIdx)->BFCR &= ~(LTDC_LxBFCR_BF2 | LTDC_LxBFCR_BF1);
+ LTDC_LAYER(hltdc, LayerIdx)->BFCR = (pLayerCfg->BlendingFactor1 | pLayerCfg->BlendingFactor2);
+
+ /* Configure the color frame buffer start address */
+ LTDC_LAYER(hltdc, LayerIdx)->CFBAR &= ~(LTDC_LxCFBAR_CFBADD);
+ LTDC_LAYER(hltdc, LayerIdx)->CFBAR = (pLayerCfg->FBStartAdress);
+
+ if (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888)
+ {
+ tmp = 4U;
+ }
+ else if (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_RGB888)
+ {
+ tmp = 3U;
+ }
+ else if ((pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_ARGB4444) || \
+ (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_RGB565) || \
+ (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_ARGB1555) || \
+ (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_AL88))
+ {
+ tmp = 2U;
+ }
+ else
+ {
+ tmp = 1U;
+ }
+
+ /* Configure the color frame buffer pitch in byte */
+ LTDC_LAYER(hltdc, LayerIdx)->CFBLR &= ~(LTDC_LxCFBLR_CFBLL | LTDC_LxCFBLR_CFBP);
+ LTDC_LAYER(hltdc, LayerIdx)->CFBLR = (((pLayerCfg->ImageWidth * tmp) << 16U) | (((pLayerCfg->WindowX1 - pLayerCfg->WindowX0) * tmp) + 7U));
+ /* Configure the frame buffer line number */
+ LTDC_LAYER(hltdc, LayerIdx)->CFBLNR &= ~(LTDC_LxCFBLNR_CFBLNBR);
+ LTDC_LAYER(hltdc, LayerIdx)->CFBLNR = (pLayerCfg->ImageHeight);
+
+ /* Enable LTDC_Layer by setting LEN bit */
+ LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_LEN;
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#endif /* LTDC */
+
+#endif /* HAL_LTDC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_ltdc_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_ltdc_ex.c
new file mode 100644
index 0000000000..b0bafd74cd
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_ltdc_ex.c
@@ -0,0 +1,149 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_ltdc_ex.c
+ * @author MCD Application Team
+ * @brief LTDC Extension HAL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#if defined(HAL_LTDC_MODULE_ENABLED) && defined(HAL_DSI_MODULE_ENABLED)
+
+#if defined (LTDC) && defined (DSI)
+
+/** @defgroup LTDCEx LTDCEx
+ * @brief LTDC HAL module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup LTDCEx_Exported_Functions LTDC Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup LTDCEx_Exported_Functions_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the LTDC
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Retrieve common parameters from DSI Video mode configuration structure
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param VidCfg pointer to a DSI_VidCfgTypeDef structure that contains
+ * the DSI video mode configuration parameters
+ * @note The implementation of this function is taking into account the LTDC
+ * polarities inversion as described in the current LTDC specification
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDCEx_StructInitFromVideoConfig(LTDC_HandleTypeDef *hltdc, DSI_VidCfgTypeDef *VidCfg)
+{
+ /* Retrieve signal polarities from DSI */
+
+ /* The following polarity is inverted:
+ LTDC_DEPOLARITY_AL <-> LTDC_DEPOLARITY_AH */
+
+ /* Note 1 : Code in line w/ Current LTDC specification */
+ hltdc->Init.DEPolarity = (VidCfg->DEPolarity == DSI_DATA_ENABLE_ACTIVE_HIGH) ? LTDC_DEPOLARITY_AL : LTDC_DEPOLARITY_AH;
+ hltdc->Init.VSPolarity = (VidCfg->VSPolarity == DSI_VSYNC_ACTIVE_HIGH) ? LTDC_VSPOLARITY_AH : LTDC_VSPOLARITY_AL;
+ hltdc->Init.HSPolarity = (VidCfg->HSPolarity == DSI_HSYNC_ACTIVE_HIGH) ? LTDC_HSPOLARITY_AH : LTDC_HSPOLARITY_AL;
+
+ /* Note 2: Code to be used in case LTDC polarities inversion updated in the specification */
+ /* hltdc->Init.DEPolarity = VidCfg->DEPolarity << 29;
+ hltdc->Init.VSPolarity = VidCfg->VSPolarity << 29;
+ hltdc->Init.HSPolarity = VidCfg->HSPolarity << 29; */
+
+ /* Retrieve vertical timing parameters from DSI */
+ hltdc->Init.VerticalSync = VidCfg->VerticalSyncActive - 1U;
+ hltdc->Init.AccumulatedVBP = VidCfg->VerticalSyncActive + VidCfg->VerticalBackPorch - 1U;
+ hltdc->Init.AccumulatedActiveH = VidCfg->VerticalSyncActive + VidCfg->VerticalBackPorch + VidCfg->VerticalActive - 1U;
+ hltdc->Init.TotalHeigh = VidCfg->VerticalSyncActive + VidCfg->VerticalBackPorch + VidCfg->VerticalActive + VidCfg->VerticalFrontPorch - 1U;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Retrieve common parameters from DSI Adapted command mode configuration structure
+ * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains
+ * the configuration information for the LTDC.
+ * @param CmdCfg pointer to a DSI_CmdCfgTypeDef structure that contains
+ * the DSI command mode configuration parameters
+ * @note The implementation of this function is taking into account the LTDC
+ * polarities inversion as described in the current LTDC specification
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LTDCEx_StructInitFromAdaptedCommandConfig(LTDC_HandleTypeDef *hltdc, DSI_CmdCfgTypeDef *CmdCfg)
+{
+ /* Retrieve signal polarities from DSI */
+
+ /* The following polarities are inverted:
+ LTDC_DEPOLARITY_AL <-> LTDC_DEPOLARITY_AH
+ LTDC_VSPOLARITY_AL <-> LTDC_VSPOLARITY_AH
+ LTDC_HSPOLARITY_AL <-> LTDC_HSPOLARITY_AH)*/
+
+ /* Note 1 : Code in line w/ Current LTDC specification */
+ hltdc->Init.DEPolarity = (CmdCfg->DEPolarity == DSI_DATA_ENABLE_ACTIVE_HIGH) ? LTDC_DEPOLARITY_AL : LTDC_DEPOLARITY_AH;
+ hltdc->Init.VSPolarity = (CmdCfg->VSPolarity == DSI_VSYNC_ACTIVE_HIGH) ? LTDC_VSPOLARITY_AL : LTDC_VSPOLARITY_AH;
+ hltdc->Init.HSPolarity = (CmdCfg->HSPolarity == DSI_HSYNC_ACTIVE_HIGH) ? LTDC_HSPOLARITY_AL : LTDC_HSPOLARITY_AH;
+
+ /* Note 2: Code to be used in case LTDC polarities inversion updated in the specification */
+ /* hltdc->Init.DEPolarity = CmdCfg->DEPolarity << 29;
+ hltdc->Init.VSPolarity = CmdCfg->VSPolarity << 29;
+ hltdc->Init.HSPolarity = CmdCfg->HSPolarity << 29; */
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* LTDC && DSI */
+
+#endif /* HAL_LTCD_MODULE_ENABLED && HAL_DSI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdios.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdios.c
new file mode 100644
index 0000000000..b08894ee4a
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdios.c
@@ -0,0 +1,957 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_mdios.c
+ * @author MCD Application Team
+ * @brief MDIOS HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the MDIOS Peripheral.
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ *
+ *
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The MDIOS HAL driver can be used as follow:
+
+ (#) Declare a MDIOS_HandleTypeDef handle structure.
+
+ (#) Initialize the MDIOS low level resources by implementing the HAL_MDIOS_MspInit() API:
+ (##) Enable the MDIOS interface clock.
+ (##) MDIOS pins configuration:
+ (+++) Enable clocks for the MDIOS GPIOs.
+ (+++) Configure the MDIOS pins as alternate function.
+ (##) NVIC configuration if you need to use interrupt process:
+ (+++) Configure the MDIOS interrupt priority.
+ (+++) Enable the NVIC MDIOS IRQ handle.
+
+ (#) Program the Port Address and the Preamble Check in the Init structure.
+
+ (#) Initialize the MDIOS registers by calling the HAL_MDIOS_Init() API.
+
+ (#) Perform direct slave read/write operations using the following APIs:
+ (##) Read the value of a DINn register: HAL_MDIOS_ReadReg()
+ (##) Write a value to a DOUTn register: HAL_MDIOS_WriteReg()
+
+ (#) Get the Master read/write operations flags using the following APIs:
+ (##) Bit map of DOUTn registers read by Master: HAL_MDIOS_GetReadRegAddress()
+ (##) Bit map of DINn registers written by Master : HAL_MDIOS_GetWrittenRegAddress()
+
+ (#) Clear the read/write flags using the following APIs:
+ (##) Clear read flags of a set of registers: HAL_MDIOS_ClearReadRegAddress()
+ (##) Clear write flags of a set of registers: HAL_MDIOS_ClearWriteRegAddress()
+
+ (#) Enable interrupts on events using HAL_MDIOS_EnableEvents(), when called
+ the MDIOS will generate an interrupt in the following cases:
+ (##) a DINn register written by the Master
+ (##) a DOUTn register read by the Master
+ (##) an error occur
+
+ (@) A callback is executed for each genereted interrupt, so the driver provide the following
+ HAL_MDIOS_WriteCpltCallback(), HAL_MDIOS_ReadCpltCallback() and HAL_MDIOS_ErrorCallback()
+ (@) HAL_MDIOS_IRQHandler() must be called from the MDIOS IRQ Handler, to handle the interrupt
+ and execute the previous callbacks
+
+ (#) Reset the MDIOS peripheral and all related ressources by calling the HAL_MDIOS_DeInit() API.
+ (##) HAL_MDIOS_MspDeInit() must be implemented to reset low level ressources
+ (GPIO, Clocks, NVIC configuration ...)
+
+ *** Callback registration ***
+ =============================================
+
+ The compilation define USE_HAL_MDIOS_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Function @ref HAL_MDIOS_RegisterCallback() to register an interrupt callback.
+
+ Function @ref HAL_MDIOS_RegisterCallback() allows to register following callbacks:
+ (+) WriteCpltCallback : Write Complete Callback.
+ (+) ReadCpltCallback : Read Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) WakeUpCallback : Wake UP Callback
+ (+) MspInitCallback : MspInit Callback.
+ (+) MspDeInitCallback : MspDeInit Callback.
+
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function @ref HAL_MDIOS_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ @ref HAL_MDIOS_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) WriteCpltCallback : Write Complete Callback.
+ (+) ReadCpltCallback : Read Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) WakeUpCallback : Wake UP Callback
+ (+) MspInitCallback : MspInit Callback.
+ (+) MspDeInitCallback : MspDeInit Callback.
+
+ By default, after the HAL_MDIOS_Init and when the state is HAL_MDIOS_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples @ref HAL_MDIOS_WriteCpltCallback(), @ref HAL_MDIOS_ReadCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak function in the HAL_MDIOS_Init/ @ref HAL_MDIOS_DeInit only when
+ these callbacks are null (not registered beforehand).
+ if not, MspInit or MspDeInit are not null, the HAL_MDIOS_Init/ @ref HAL_MDIOS_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in HAL_MDIOS_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_MDIOS_STATE_READY or HAL_MDIOS_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 @ref HAL_MDIOS_RegisterCallback() before calling @ref HAL_MDIOS_DeInit
+ or HAL_MDIOS_Init function.
+
+ When The compilation define USE_HAL_MDIOS_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#if defined (MDIOS)
+/** @defgroup MDIOS MDIOS
+ * @brief HAL MDIOS module driver
+ * @{
+ */
+#ifdef HAL_MDIOS_MODULE_ENABLED
+
+
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define MDIOS_PORT_ADDRESS_SHIFT ((uint32_t)8)
+#define MDIOS_ALL_REG_FLAG ((uint32_t)0xFFFFFFFFU)
+#define MDIOS_ALL_ERRORS_FLAG ((uint32_t)(MDIOS_SR_PERF | MDIOS_SR_SERF | MDIOS_SR_TERF))
+
+#define MDIOS_DIN_BASE_ADDR (MDIOS_BASE + 0x100U)
+#define MDIOS_DOUT_BASE_ADDR (MDIOS_BASE + 0x180U)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+static void MDIOS_InitCallbacksToDefault(MDIOS_HandleTypeDef *hmdios);
+#endif /* USE_HAL_MDIOS_REGISTER_CALLBACKS */
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup MDIOS_Exported_Functions MDIOS Exported Functions
+ * @{
+ */
+
+/** @defgroup MDIOS_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 MDIOS
+ (+) The following parameters can be configured:
+ (++) Port Address
+ (++) Preamble Check
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the MDIOS according to the specified parameters in
+ * the MDIOS_InitTypeDef and creates the associated handle .
+ * @param hmdios: pointer to a MDIOS_HandleTypeDef structure that contains
+ * the configuration information for MDIOS module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDIOS_Init(MDIOS_HandleTypeDef *hmdios)
+{
+ uint32_t tmpcr;
+
+ /* Check the MDIOS handle allocation */
+ if(hmdios == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_MDIOS_ALL_INSTANCE(hmdios->Instance));
+ assert_param(IS_MDIOS_PORTADDRESS(hmdios->Init.PortAddress));
+ assert_param(IS_MDIOS_PREAMBLECHECK(hmdios->Init.PreambleCheck));
+
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+
+ if(hmdios->State == HAL_MDIOS_STATE_RESET)
+ {
+ MDIOS_InitCallbacksToDefault(hmdios);
+
+ if(hmdios->MspInitCallback == NULL)
+ {
+ hmdios->MspInitCallback = HAL_MDIOS_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hmdios->MspInitCallback(hmdios);
+ }
+
+#else
+
+ if(hmdios->State == HAL_MDIOS_STATE_RESET)
+ {
+ /* Init the low level hardware */
+ HAL_MDIOS_MspInit(hmdios);
+ }
+
+#endif /* (USE_HAL_MDIOS_REGISTER_CALLBACKS) */
+
+ /* Change the MDIOS state */
+ hmdios->State = HAL_MDIOS_STATE_BUSY;
+
+ /* Get the MDIOS CR value */
+ tmpcr = hmdios->Instance->CR;
+
+ /* Clear PORT_ADDRESS, DPC and EN bits */
+ tmpcr &= ((uint32_t)~(MDIOS_CR_EN | MDIOS_CR_DPC | MDIOS_CR_PORT_ADDRESS));
+
+ /* Set MDIOS control parametrs and enable the peripheral */
+ tmpcr |= (uint32_t)(((hmdios->Init.PortAddress) << MDIOS_PORT_ADDRESS_SHIFT) |\
+ (hmdios->Init.PreambleCheck) | \
+ (MDIOS_CR_EN));
+
+ /* Write the MDIOS CR */
+ hmdios->Instance->CR = tmpcr;
+
+ hmdios->ErrorCode = HAL_MDIOS_ERROR_NONE;
+
+ /* Change the MDIOS state */
+ hmdios->State = HAL_MDIOS_STATE_READY;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmdios);
+
+ /* Return function status */
+ return HAL_OK;
+
+}
+
+/**
+ * @brief DeInitializes the MDIOS peripheral.
+ * @param hmdios: MDIOS handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDIOS_DeInit(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Check the MDIOS handle allocation */
+ if(hmdios == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_MDIOS_ALL_INSTANCE(hmdios->Instance));
+
+ /* Change the MDIOS state */
+ hmdios->State = HAL_MDIOS_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_MDIOS_DISABLE(hmdios);
+
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+
+ if(hmdios->MspDeInitCallback == NULL)
+ {
+ hmdios->MspDeInitCallback = HAL_MDIOS_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ hmdios->MspDeInitCallback(hmdios);
+#else
+
+ /* DeInit the low level hardware */
+ HAL_MDIOS_MspDeInit(hmdios);
+
+#endif /* (USE_HAL_MDIOS_REGISTER_CALLBACKS) */
+
+ /* Change the MDIOS state */
+ hmdios->State = HAL_MDIOS_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmdios);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief MDIOS MSP Init
+ * @param hmdios: mdios handle
+ * @retval None
+ */
+ __weak void HAL_MDIOS_MspInit(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdios);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MDIOS_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief MDIOS MSP DeInit
+ * @param hmdios: mdios handle
+ * @retval None
+ */
+ __weak void HAL_MDIOS_MspDeInit(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdios);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MDIOS_MspDeInit can be implemented in the user file
+ */
+}
+
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User MDIOS Callback
+ * To be used instead of the weak predefined callback
+ * @param hmdios mdios handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_MDIOS_WRITE_COMPLETE_CB_ID Write Complete Callback ID
+ * @arg @ref HAL_MDIOS_READ_COMPLETE_CB_ID Read Complete Callback ID
+ * @arg @ref HAL_MDIOS_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_MDIOS_WAKEUP_CB_ID Wake Up Callback ID
+ * @arg @ref HAL_MDIOS_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_MDIOS_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_MDIOS_RegisterCallback(MDIOS_HandleTypeDef *hmdios, HAL_MDIOS_CallbackIDTypeDef CallbackID, pMDIOS_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ hmdios->ErrorCode |= HAL_MDIOS_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hmdios);
+
+ if(hmdios->State == HAL_MDIOS_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_MDIOS_WRITE_COMPLETE_CB_ID :
+ hmdios->WriteCpltCallback = pCallback;
+ break;
+
+ case HAL_MDIOS_READ_COMPLETE_CB_ID :
+ hmdios->ReadCpltCallback = pCallback;
+ break;
+
+ case HAL_MDIOS_ERROR_CB_ID :
+ hmdios->ErrorCallback = pCallback;
+ break;
+
+ case HAL_MDIOS_WAKEUP_CB_ID :
+ hmdios->WakeUpCallback = pCallback;
+ break;
+
+ case HAL_MDIOS_MSPINIT_CB_ID :
+ hmdios->MspInitCallback = pCallback;
+ break;
+
+ case HAL_MDIOS_MSPDEINIT_CB_ID :
+ hmdios->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hmdios->ErrorCode |= HAL_MDIOS_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(hmdios->State == HAL_MDIOS_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_MDIOS_MSPINIT_CB_ID :
+ hmdios->MspInitCallback = pCallback;
+ break;
+
+ case HAL_MDIOS_MSPDEINIT_CB_ID :
+ hmdios->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hmdios->ErrorCode |= HAL_MDIOS_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hmdios->ErrorCode |= HAL_MDIOS_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmdios);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an MDIOS Callback
+ * MDIOS callabck is redirected to the weak predefined callback
+ * @param hmdios mdios handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_MDIOS_WRITE_COMPLETE_CB_ID Write Complete Callback ID
+ * @arg @ref HAL_MDIOS_READ_COMPLETE_CB_ID Read Complete Callback ID
+ * @arg @ref HAL_MDIOS_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_MDIOS_WAKEUP_CB_ID Wake Up Callback ID
+ * @arg @ref HAL_MDIOS_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_MDIOS_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_MDIOS_UnRegisterCallback(MDIOS_HandleTypeDef *hmdios, HAL_MDIOS_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hmdios);
+
+ if(hmdios->State == HAL_MDIOS_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_MDIOS_WRITE_COMPLETE_CB_ID :
+ hmdios->WriteCpltCallback = HAL_MDIOS_WriteCpltCallback;
+ break;
+
+ case HAL_MDIOS_READ_COMPLETE_CB_ID :
+ hmdios->ReadCpltCallback = HAL_MDIOS_ReadCpltCallback;
+ break;
+
+ case HAL_MDIOS_ERROR_CB_ID :
+ hmdios->ErrorCallback = HAL_MDIOS_ErrorCallback;
+ break;
+
+ case HAL_MDIOS_WAKEUP_CB_ID :
+ hmdios->WakeUpCallback = HAL_MDIOS_WakeUpCallback;
+ break;
+
+ case HAL_MDIOS_MSPINIT_CB_ID :
+ hmdios->MspInitCallback = HAL_MDIOS_MspInit;
+ break;
+
+ case HAL_MDIOS_MSPDEINIT_CB_ID :
+ hmdios->MspDeInitCallback = HAL_MDIOS_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hmdios->ErrorCode |= HAL_MDIOS_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(hmdios->State == HAL_MDIOS_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_MDIOS_MSPINIT_CB_ID :
+ hmdios->MspInitCallback = HAL_MDIOS_MspInit;
+ break;
+
+ case HAL_MDIOS_MSPDEINIT_CB_ID :
+ hmdios->MspDeInitCallback = HAL_MDIOS_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hmdios->ErrorCode |= HAL_MDIOS_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hmdios->ErrorCode |= HAL_MDIOS_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmdios);
+
+ return status;
+}
+#endif /* USE_HAL_MDIOS_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup MDIOS_Exported_Functions_Group2 IO operation functions
+ * @brief MDIOS Read/Write functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ This subsection provides a set of functions allowing to manage the MDIOS
+ read and write operations.
+
+ (#) APIs that allow to the MDIOS to read/write from/to the
+ values of one of the DINn/DOUTn registers:
+ (+) Read the value of a DINn register: HAL_MDIOS_ReadReg()
+ (+) Write a value to a DOUTn register: HAL_MDIOS_WriteReg()
+
+ (#) APIs that provide if there are some Slave registres have been
+ read or written by the Master:
+ (+) DOUTn registers read by Master: HAL_MDIOS_GetReadRegAddress()
+ (+) DINn registers written by Master : HAL_MDIOS_GetWrittenRegAddress()
+
+ (#) APIs that Clear the read/write flags:
+ (+) Clear read registers flags: HAL_MDIOS_ClearReadRegAddress()
+ (+) Clear write registers flags: HAL_MDIOS_ClearWriteRegAddress()
+
+ (#) A set of Callbacks are provided:
+ (+) HAL_MDIOS_WriteCpltCallback()
+ (+) HAL_MDIOS_ReadCpltCallback()
+ (+) HAL_MDIOS_ErrorCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Writes to an MDIOS output register
+ * @param hmdios: mdios handle
+ * @param RegNum: MDIOS output register address
+ * @param Data: Data to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDIOS_WriteReg(MDIOS_HandleTypeDef *hmdios, uint32_t RegNum, uint16_t Data)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_MDIOS_REGISTER(RegNum));
+
+ /* Process Locked */
+ __HAL_LOCK(hmdios);
+
+ /* Get the addr of output register to be written by the MDIOS */
+ tmpreg = MDIOS_DOUT_BASE_ADDR + (4U * RegNum);
+
+ /* Write to DOUTn register */
+ *((uint32_t *)tmpreg) = Data;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hmdios);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reads an MDIOS input register
+ * @param hmdios: mdios handle
+ * @param RegNum: MDIOS input register address
+ * @param pData: pointer to Data
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDIOS_ReadReg(MDIOS_HandleTypeDef *hmdios, uint32_t RegNum, uint16_t *pData)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_MDIOS_REGISTER(RegNum));
+
+ /* Process Locked */
+ __HAL_LOCK(hmdios);
+
+ /* Get the addr of input register to be read by the MDIOS */
+ tmpreg = MDIOS_DIN_BASE_ADDR + (4U * RegNum);
+
+ /* Read DINn register */
+ *pData = (uint16_t)(*((uint32_t *)tmpreg));
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hmdios);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Gets Written registers by MDIO master
+ * @param hmdios: mdios handle
+ * @retval bit map of written registers addresses
+ */
+uint32_t HAL_MDIOS_GetWrittenRegAddress(MDIOS_HandleTypeDef *hmdios)
+{
+ return hmdios->Instance->WRFR;
+}
+
+/**
+ * @brief Gets Read registers by MDIO master
+ * @param hmdios: mdios handle
+ * @retval bit map of read registers addresses
+ */
+uint32_t HAL_MDIOS_GetReadRegAddress(MDIOS_HandleTypeDef *hmdios)
+{
+ return hmdios->Instance->RDFR;
+}
+
+/**
+ * @brief Clears Write registers flag
+ * @param hmdios: mdios handle
+ * @param RegNum: registers addresses to be cleared
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDIOS_ClearWriteRegAddress(MDIOS_HandleTypeDef *hmdios, uint32_t RegNum)
+{
+ /* Check the parameters */
+ assert_param(IS_MDIOS_REGISTER(RegNum));
+
+ /* Process Locked */
+ __HAL_LOCK(hmdios);
+
+ /* Clear write registers flags */
+ hmdios->Instance->CWRFR |= (RegNum);
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmdios);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Clears Read register flag
+ * @param hmdios: mdios handle
+ * @param RegNum: registers addresses to be cleared
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDIOS_ClearReadRegAddress(MDIOS_HandleTypeDef *hmdios, uint32_t RegNum)
+{
+ /* Check the parameters */
+ assert_param(IS_MDIOS_REGISTER(RegNum));
+
+ /* Process Locked */
+ __HAL_LOCK(hmdios);
+
+ /* Clear read registers flags */
+ hmdios->Instance->CRDFR |= (RegNum);
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmdios);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables Events for MDIOS peripheral
+ * @param hmdios: mdios handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDIOS_EnableEvents(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Process Locked */
+ __HAL_LOCK(hmdios);
+
+ /* Enable MDIOS interrupts: Register Write, Register Read and Error ITs */
+ __HAL_MDIOS_ENABLE_IT(hmdios, (MDIOS_IT_WRITE | MDIOS_IT_READ | MDIOS_IT_ERROR));
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hmdios);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles MDIOS interrupt request.
+ * @param hmdios: MDIOS handle
+ * @retval None
+ */
+void HAL_MDIOS_IRQHandler(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Write Register Interrupt enabled ? */
+ if(__HAL_MDIOS_GET_IT_SOURCE(hmdios, MDIOS_IT_WRITE) != (uint32_t)RESET)
+ {
+ /* Write register flag */
+ if(HAL_MDIOS_GetWrittenRegAddress(hmdios) != (uint32_t)RESET)
+ {
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+ /*Call registered Write complete callback*/
+ hmdios->WriteCpltCallback(hmdios);
+#else
+ /* Write callback function */
+ HAL_MDIOS_WriteCpltCallback(hmdios);
+#endif /* USE_HAL_MDIOS_REGISTER_CALLBACKS */
+
+ /* Clear write register flag */
+ hmdios->Instance->CWRFR |= MDIOS_ALL_REG_FLAG;
+ }
+ }
+
+ /* Read Register Interrupt enabled ? */
+ if(__HAL_MDIOS_GET_IT_SOURCE(hmdios, MDIOS_IT_READ) != (uint32_t)RESET)
+ {
+ /* Read register flag */
+ if(HAL_MDIOS_GetReadRegAddress(hmdios) != (uint32_t)RESET)
+ {
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+ /*Call registered Read complete callback*/
+ hmdios->ReadCpltCallback(hmdios);
+#else
+ /* Read callback function */
+ HAL_MDIOS_ReadCpltCallback(hmdios);
+#endif /* USE_HAL_MDIOS_REGISTER_CALLBACKS */
+
+ /* Clear read register flag */
+ hmdios->Instance->CRDFR |= MDIOS_ALL_REG_FLAG;
+ }
+ }
+
+ /* Error Interrupt enabled ? */
+ if(__HAL_MDIOS_GET_IT_SOURCE(hmdios, MDIOS_IT_ERROR) != (uint32_t)RESET)
+ {
+ /* All Errors Flag */
+ if(__HAL_MDIOS_GET_ERROR_FLAG(hmdios, MDIOS_ALL_ERRORS_FLAG) != (uint32_t)RESET)
+ {
+ hmdios->ErrorCode |= HAL_MDIOS_ERROR_DATA;
+
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+ /*Call registered Error callback*/
+ hmdios->ErrorCallback(hmdios);
+#else
+ /* Error Callback */
+ HAL_MDIOS_ErrorCallback(hmdios);
+#endif /* USE_HAL_MDIOS_REGISTER_CALLBACKS */
+
+ /* Clear errors flag */
+ __HAL_MDIOS_CLEAR_ERROR_FLAG(hmdios, MDIOS_ALL_ERRORS_FLAG);
+ }
+ hmdios->ErrorCode = HAL_MDIOS_ERROR_NONE;
+ }
+#if defined(DUAL_CORE)
+
+ if (HAL_GetCurrentCPUID() == CM7_CPUID)
+ {
+ if(__HAL_MDIOS_WAKEUP_EXTI_GET_FLAG(MDIOS_WAKEUP_EXTI_LINE) != (uint32_t)RESET)
+ {
+ /* Clear MDIOS WAKEUP Exti pending bit */
+ __HAL_MDIOS_WAKEUP_EXTI_CLEAR_FLAG(MDIOS_WAKEUP_EXTI_LINE);
+
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+ /*Call registered WakeUp callback*/
+ hmdios->WakeUpCallback(hmdios);
+#else
+ /* MDIOS WAKEUP callback */
+ HAL_MDIOS_WakeUpCallback(hmdios);
+#endif /* USE_HAL_MDIOS_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ if(__HAL_MDIOS_WAKEUP_EXTID2_GET_FLAG(MDIOS_WAKEUP_EXTI_LINE) != (uint32_t)RESET)
+ {
+ /* Clear MDIOS WAKEUP Exti D2 pending bit */
+ __HAL_MDIOS_WAKEUP_EXTID2_CLEAR_FLAG(MDIOS_WAKEUP_EXTI_LINE);
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+ /*Call registered WakeUp callback*/
+ hmdios->WakeUpCallback(hmdios);
+#else
+ /* MDIOS WAKEUP callback */
+ HAL_MDIOS_WakeUpCallback(hmdios);
+#endif /* USE_HAL_MDIOS_REGISTER_CALLBACKS */
+ }
+ }
+#else
+ /* check MDIOS WAKEUP exti flag */
+ if(__HAL_MDIOS_WAKEUP_EXTI_GET_FLAG(MDIOS_WAKEUP_EXTI_LINE) != (uint32_t)RESET)
+ {
+ /* Clear MDIOS WAKEUP Exti pending bit */
+ __HAL_MDIOS_WAKEUP_EXTI_CLEAR_FLAG(MDIOS_WAKEUP_EXTI_LINE);
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+ /*Call registered WakeUp callback*/
+ hmdios->WakeUpCallback(hmdios);
+#else
+ /* MDIOS WAKEUP callback */
+ HAL_MDIOS_WakeUpCallback(hmdios);
+#endif /* USE_HAL_MDIOS_REGISTER_CALLBACKS */
+ }
+#endif
+}
+
+/**
+ * @brief Write Complete Callback
+ * @param hmdios: mdios handle
+ * @retval None
+ */
+ __weak void HAL_MDIOS_WriteCpltCallback(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdios);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MDIOS_WriteCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Read Complete Callback
+ * @param hmdios: mdios handle
+ * @retval None
+ */
+ __weak void HAL_MDIOS_ReadCpltCallback(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdios);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MDIOS_ReadCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Error Callback
+ * @param hmdios: mdios handle
+ * @retval None
+ */
+ __weak void HAL_MDIOS_ErrorCallback(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdios);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MDIOS_ErrorCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief MDIOS WAKEUP interrupt callback
+ * @param hmdios: mdios handle
+ * @retval None
+ */
+__weak void HAL_MDIOS_WakeUpCallback(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdios);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_MDIOS_WakeUpCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup MDIOS_Exported_Functions_Group3 Peripheral Control functions
+ * @brief MDIOS control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the MDIOS.
+ (+) HAL_MDIOS_GetState() API, helpful to check in run-time the state.
+ (+) HAL_MDIOS_GetError() API, returns the errors code of the HAL state machine.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Gets MDIOS error code
+ * @param hmdios: mdios handle
+ * @retval mdios error code
+ */
+uint32_t HAL_MDIOS_GetError(MDIOS_HandleTypeDef *hmdios)
+{
+ /* return the error code */
+ return hmdios->ErrorCode;
+}
+
+/**
+ * @brief Return the MDIOS HAL state
+ * @param hmdios: mdios handle
+ * @retval HAL state
+ */
+HAL_MDIOS_StateTypeDef HAL_MDIOS_GetState(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Return MDIOS state */
+ return hmdios->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#if (USE_HAL_MDIOS_REGISTER_CALLBACKS == 1)
+static void MDIOS_InitCallbacksToDefault(MDIOS_HandleTypeDef *hmdios)
+{
+ /* Init the MDIOS Callback settings */
+ hmdios->WriteCpltCallback = HAL_MDIOS_WriteCpltCallback; /* Legacy weak WriteCpltCallback */
+ hmdios->ReadCpltCallback = HAL_MDIOS_ReadCpltCallback; /* Legacy weak ReadCpltCallback */
+ hmdios->ErrorCallback = HAL_MDIOS_ErrorCallback; /* Legacy weak ErrorCallback */
+ hmdios->WakeUpCallback = HAL_MDIOS_WakeUpCallback; /* Legacy weak WakeUpCallback */
+}
+#endif /* USE_HAL_MDIOS_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+#endif /* HAL_MDIOS_MODULE_ENABLED */
+/**
+ * @}
+ */
+#endif /* MDIOS */
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c
new file mode 100644
index 0000000000..08498c4605
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mdma.c
@@ -0,0 +1,1901 @@
+/**
+ ******************************************************************************
+ * @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
+ @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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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, 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) retrun 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 retrun 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(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(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 transfered
+ * @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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_mmc.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mmc.c
new file mode 100644
index 0000000000..6bbb14b79d
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mmc.c
@@ -0,0 +1,3054 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_mmc.c
+ * @author MCD Application Team
+ * @brief MMC card HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Secure Digital (MMC) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + MMC card Control functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver implements a high level communication layer for read and write from/to
+ this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by
+ the user in HAL_MMC_MspInit() function (MSP layer).
+ Basically, the MSP layer configuration should be the same as we provide in the
+ examples.
+ You can easily tailor this configuration according to hardware resources.
+
+ [..]
+ This driver is a generic layered driver for SDMMC memories which uses the HAL
+ SDMMC driver functions to interface with MMC and eMMC cards devices.
+ It is used as follows:
+
+ (#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API:
+ (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE();
+ (##) SDMMC pins configuration for MMC card
+ (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
+ (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
+ and according to your pin assignment;
+ (##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT()
+ and HAL_MMC_WriteBlocks_IT() APIs).
+ (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
+ (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
+ (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
+ and __HAL_MMC_DISABLE_IT() inside the communication process.
+ (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
+ and __HAL_MMC_CLEAR_IT()
+ (##) No general propose DMA Configuration is needed, an Internal DMA for SDMMC Peripheral are used.
+
+ (#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization
+
+
+ *** MMC Card Initialization and configuration ***
+ ================================================
+ [..]
+ To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes
+ SDMMC Peripheral (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer).
+ This function provide the following operations:
+
+ (#) Initialize the SDMMC peripheral interface with defaullt configuration.
+ The initialization process is done at 400KHz. You can change or adapt
+ this frequency by adjusting the "ClockDiv" field.
+ The MMC Card frequency (SDMMC_CK) is computed as follows:
+
+ SDMMC_CK = SDMMCCLK / (2 * ClockDiv)
+
+ In initialization mode and according to the MMC Card standard,
+ make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
+
+ This phase of initialization is done through SDMMC_Init() and
+ SDMMC_PowerState_ON() SDMMC low level APIs.
+
+ (#) Initialize the MMC card. The API used is HAL_MMC_InitCard().
+ This phase allows the card initialization and identification
+ and check the MMC Card type (Standard Capacity or High Capacity)
+ The initialization flow is compatible with MMC standard.
+
+ This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case
+ of plug-off plug-in.
+
+ (#) Configure the MMC Card Data transfer frequency. By Default, the card transfer
+ frequency by adjusting the "ClockDiv" field.
+ In transfer mode and according to the MMC Card standard, make sure that the
+ SDMMC_CK frequency doesn't exceed 25MHz and 100MHz in High-speed mode switch.
+
+ (#) Select the corresponding MMC Card according to the address read with the step 2.
+
+ (#) Configure the MMC Card in wide bus mode: 4-bits data.
+
+ *** MMC Card Read operation ***
+ ==============================
+ [..]
+ (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_MMC_GetCardState() function for MMC card state.
+
+ (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_MMC_GetCardState() function for MMC card state.
+ You could also check the DMA transfer process through the MMC Rx interrupt event.
+
+ (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
+ This function allows the read of 512 bytes blocks.
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_MMC_GetCardState() function for MMC card state.
+ You could also check the IT transfer process through the MMC Rx interrupt event.
+
+ *** MMC Card Write operation ***
+ ===============================
+ [..]
+ (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_MMC_GetCardState() function for MMC card state.
+
+ (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 byte).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_MMC_GetCardState() function for MMC card state.
+ You could also check the DMA transfer process through the MMC Tx interrupt event.
+
+ (+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT().
+ This function allows the read of 512 bytes blocks.
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_MMC_GetCardState() function for MMC card state.
+ You could also check the IT transfer process through the MMC Tx interrupt event.
+
+ *** MMC card information ***
+ ===========================
+ [..]
+ (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
+ It returns useful information about the MMC card such as block size, card type,
+ block number ...
+
+ *** MMC card CSD register ***
+ ============================
+ [..]
+ (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
+ Some of the CSD parameters are useful for card initialization and identification.
+
+ *** MMC card CID register ***
+ ============================
+ [..]
+ (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
+ Some of the CID parameters are useful for card initialization and identification.
+
+ *** MMC HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in MMC HAL driver.
+
+ (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
+ (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
+ (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
+ (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
+
+ [..]
+ (@) You can refer to the MMC HAL driver header file for more useful macros
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ Use Functions @ref HAL_MMC_RegisterCallback() to register a user callback,
+ it allows to register following callbacks:
+ (+) TxCpltCallback : callback when a transmission transfer is completed.
+ (+) RxCpltCallback : callback when a reception transfer is completed.
+ (+) ErrorCallback : callback when error occurs.
+ (+) AbortCpltCallback : callback when abort is completed.
+ (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed.
+ (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed.
+ (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed.
+ (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed.
+ (+) MspInitCallback : MMC MspInit.
+ (+) MspDeInitCallback : MMC MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function @ref HAL_MMC_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function. It allows to reset following callbacks:
+ (+) TxCpltCallback : callback when a transmission transfer is completed.
+ (+) RxCpltCallback : callback when a reception transfer is completed.
+ (+) ErrorCallback : callback when error occurs.
+ (+) AbortCpltCallback : callback when abort is completed.
+ (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed.
+ (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed.
+ (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed.
+ (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed.
+ (+) MspInitCallback : MMC MspInit.
+ (+) MspDeInitCallback : MMC MspDeInit.
+ This function) takes as parameters the HAL peripheral handle and the Callback ID.
+
+ By default, after the @ref HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_MMC_Init
+ and @ref HAL_MMC_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_MMC_Init and @ref HAL_MMC_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 @ref HAL_MMC_RegisterCallback before calling @ref HAL_MMC_DeInit
+ or @ref HAL_MMC_Init function.
+
+ When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup MMC MMC
+ * @brief MMC HAL module driver
+ * @{
+ */
+
+#ifdef HAL_MMC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup MMC_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup MMC_Private_Functions MMC Private Functions
+ * @{
+ */
+static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
+static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);
+static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
+static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
+static void MMC_Write_IT(MMC_HandleTypeDef *hmmc);
+static void MMC_Read_IT(MMC_HandleTypeDef *hmmc);
+static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state);
+static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state);
+HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout);
+
+
+/**
+ * @}
+ */
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup MMC_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup MMC_Exported_Functions_Group1
+ * @brief Initialization and de-initialization functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to initialize/de-initialize the MMC
+ card device to be ready for use.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the MMC according to the specified parameters in the
+ MMC_HandleTypeDef and create the associated handle.
+ * @param hmmc: Pointer to the MMC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
+{
+ /* Check the MMC handle allocation */
+ if(hmmc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
+ assert_param(IS_SDMMC_CLOCK_EDGE(hmmc->Init.ClockEdge));
+ assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
+ assert_param(IS_SDMMC_BUS_WIDE(hmmc->Init.BusWide));
+ assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
+ assert_param(IS_SDMMC_CLKDIV(hmmc->Init.ClockDiv));
+
+ if(hmmc->State == HAL_MMC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hmmc->Lock = HAL_UNLOCKED;
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ /* Reset Callback pointers in HAL_MMC_STATE_RESET only */
+ hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
+ hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
+ hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
+ hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
+ hmmc->Read_DMADblBuf0CpltCallback = HAL_MMCEx_Read_DMADoubleBuf0CpltCallback;
+ hmmc->Read_DMADblBuf1CpltCallback = HAL_MMCEx_Read_DMADoubleBuf1CpltCallback;
+ hmmc->Write_DMADblBuf0CpltCallback = HAL_MMCEx_Write_DMADoubleBuf0CpltCallback;
+ hmmc->Write_DMADblBuf1CpltCallback = HAL_MMCEx_Write_DMADoubleBuf1CpltCallback;
+
+ if(hmmc->MspInitCallback == NULL)
+ {
+ hmmc->MspInitCallback = HAL_MMC_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hmmc->MspInitCallback(hmmc);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ HAL_MMC_MspInit(hmmc);
+#endif
+ }
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ /* Initialize the Card parameters */
+ if(HAL_MMC_InitCard(hmmc) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Initialize the error code */
+ hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Initialize the MMC operation */
+ hmmc->Context = MMC_CONTEXT_NONE;
+
+ /* Initialize the MMC state */
+ hmmc->State = HAL_MMC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the MMC Card.
+ * @param hmmc: Pointer to MMC handle
+ * @note This function initializes the MMC card. It could be used when a card
+ re-initialization is needed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
+{
+ uint32_t errorstate;
+ MMC_InitTypeDef Init;
+
+ /* Default SDMMC peripheral configuration for MMC card initialization */
+ Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
+ Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
+ Init.BusWide = SDMMC_BUS_WIDE_1B;
+ Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
+ Init.ClockDiv = SDMMC_INIT_CLK_DIV;
+
+ /* Initialize SDMMC peripheral interface with default configuration */
+ (void)SDMMC_Init(hmmc->Instance, Init);
+
+ /* Set Power State to ON */
+ (void)SDMMC_PowerState_ON(hmmc->Instance);
+
+ /* Identify card operating voltage */
+ errorstate = MMC_PowerON(hmmc);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->State = HAL_MMC_STATE_READY;
+ hmmc->ErrorCode |= errorstate;
+ return HAL_ERROR;
+ }
+
+ /* Card initialization */
+ errorstate = MMC_InitCard(hmmc);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->State = HAL_MMC_STATE_READY;
+ hmmc->ErrorCode |= errorstate;
+ return HAL_ERROR;
+ }
+
+ /* Set Block Size for Card */
+ errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief De-Initializes the MMC card.
+ * @param hmmc: Pointer to MMC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
+{
+ /* Check the MMC handle allocation */
+ if(hmmc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ /* Set MMC power state to off */
+ MMC_PowerOFF(hmmc);
+
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ if(hmmc->MspDeInitCallback == NULL)
+ {
+ hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hmmc->MspDeInitCallback(hmmc);
+#else
+ /* De-Initialize the MSP layer */
+ HAL_MMC_MspDeInit(hmmc);
+#endif
+
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+ hmmc->State = HAL_MMC_STATE_RESET;
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Initializes the MMC MSP.
+ * @param hmmc: Pointer to MMC handle
+ * @retval None
+ */
+__weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_MMC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief De-Initialize MMC MSP.
+ * @param hmmc: Pointer to MMC handle
+ * @retval None
+ */
+__weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_MMC_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup MMC_Exported_Functions_Group2
+ * @brief Data transfer functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the data
+ transfer from/to MMC card.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The Data transfer
+ * is managed by polling mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_MMC_GetCardState().
+ * @param hmmc: Pointer to MMC handle
+ * @param pData: pointer to the buffer that will contain the received data
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Number of MMC blocks to read
+ * @param Timeout: Specify timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t count, data, dataremaining;
+ uint32_t add = BlockAdd;
+ uint8_t *tempbuff = pData;
+
+ if(NULL == pData)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+
+ if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ /* Initialize data control register */
+ hmmc->Instance->DCTRL = 0U;
+
+ if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the MMC DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hmmc->Instance, &config);
+ __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
+
+ /* Read block(s) in polling mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
+
+ /* Read Multi Block command */
+ errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
+ }
+ else
+ {
+ hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
+
+ /* Read Single Block command */
+ errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
+ }
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Poll on SDMMC flags */
+ dataremaining = config.DataLength;
+ while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
+ {
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
+ {
+ /* Read data from SDMMC Rx FIFO */
+ for(count = 0U; count < 8U; count++)
+ {
+ data = SDMMC_ReadFIFO(hmmc->Instance);
+ *tempbuff = (uint8_t)(data & 0xFFU);
+ tempbuff++;
+ *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
+ tempbuff++;
+ *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
+ tempbuff++;
+ *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
+ tempbuff++;
+ }
+ dataremaining -= 32U;
+ }
+
+ if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
+ hmmc->State= HAL_MMC_STATE_READY;
+ return HAL_TIMEOUT;
+ }
+ }
+ __SDMMC_CMDTRANS_DISABLE( hmmc->Instance);
+
+ /* Send stop transmission command in case of multiblock read */
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
+ {
+ /* Send stop transmission command */
+ errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+
+ /* Get error state */
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+ else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+ else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR))
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
+
+ hmmc->State = HAL_MMC_STATE_READY;
+
+ return HAL_OK;
+ }
+ else
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Allows to write block(s) to a specified address in a card. The Data
+ * transfer is managed by polling mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_MMC_GetCardState().
+ * @param hmmc: Pointer to MMC handle
+ * @param pData: pointer to the buffer that will contain the data to transmit
+ * @param BlockAdd: Block Address where data will be written
+ * @param NumberOfBlocks: Number of MMC blocks to write
+ * @param Timeout: Specify timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t count, data, dataremaining;
+ uint32_t add = BlockAdd;
+ uint8_t *tempbuff = pData;
+
+ if(NULL == pData)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+
+ if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ /* Initialize data control register */
+ hmmc->Instance->DCTRL = 0U;
+
+ if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the MMC DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hmmc->Instance, &config);
+ __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
+
+ /* Write Blocks in Polling mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
+
+ /* Write Multi Block command */
+ errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
+ }
+ else
+ {
+ hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
+
+ /* Write Single Block command */
+ errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
+ }
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Write block(s) in polling mode */
+ dataremaining = config.DataLength;
+ while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
+ {
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
+ {
+ /* Write data to SDMMC Tx FIFO */
+ for(count = 0U; count < 8U; count++)
+ {
+ data = (uint32_t)(*tempbuff);
+ tempbuff++;
+ data |= ((uint32_t)(*tempbuff) << 8U);
+ tempbuff++;
+ data |= ((uint32_t)(*tempbuff) << 16U);
+ tempbuff++;
+ data |= ((uint32_t)(*tempbuff) << 24U);
+ tempbuff++;
+ (void)SDMMC_WriteFIFO(hmmc->Instance, &data);
+ }
+ dataremaining -= 32U;
+ }
+
+ if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_TIMEOUT;
+ }
+ }
+ __SDMMC_CMDTRANS_DISABLE( hmmc->Instance);
+
+ /* Send stop transmission command in case of multiblock write */
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
+ {
+ /* Send stop transmission command */
+ errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+
+ /* Get error state */
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+ else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+ else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR))
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
+
+ hmmc->State = HAL_MMC_STATE_READY;
+
+ return HAL_OK;
+ }
+ else
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The Data transfer
+ * is managed in interrupt mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_MMC_GetCardState().
+ * @note You could also check the IT transfer process through the MMC Rx
+ * interrupt event.
+ * @param hmmc: Pointer to MMC handle
+ * @param pData: Pointer to the buffer that will contain the received data
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Number of blocks to read.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t add = BlockAdd;
+
+ if(NULL == pData)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+
+ if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ /* Initialize data control register */
+ hmmc->Instance->DCTRL = 0U;
+
+ hmmc->pRxBuffPtr = pData;
+ hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
+
+ if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the MMC DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hmmc->Instance, &config);
+ __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
+
+ /* Read Blocks in IT mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
+
+ /* Read Multi Block command */
+ errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
+ }
+ else
+ {
+ hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
+
+ /* Read Single Block command */
+ errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
+ }
+
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | SDMMC_FLAG_RXFIFOHF));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Writes block(s) to a specified address in a card. The Data transfer
+ * is managed in interrupt mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_MMC_GetCardState().
+ * @note You could also check the IT transfer process through the MMC Tx
+ * interrupt event.
+ * @param hmmc: Pointer to MMC handle
+ * @param pData: Pointer to the buffer that will contain the data to transmit
+ * @param BlockAdd: Block Address where data will be written
+ * @param NumberOfBlocks: Number of blocks to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t add = BlockAdd;
+
+ if(NULL == pData)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+
+ if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ /* Initialize data control register */
+ hmmc->Instance->DCTRL = 0U;
+
+ hmmc->pTxBuffPtr = pData;
+ hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
+
+ if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the MMC DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hmmc->Instance, &config);
+
+ __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
+
+ /* Write Blocks in Polling mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK| MMC_CONTEXT_IT);
+
+ /* Write Multi Block command */
+ errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
+ }
+ else
+ {
+ hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
+
+ /* Write Single Block command */
+ errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
+ }
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Enable transfer interrupts */
+ __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_FLAG_TXFIFOHE));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The Data transfer
+ * is managed by DMA mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_MMC_GetCardState().
+ * @note You could also check the DMA transfer process through the MMC Rx
+ * interrupt event.
+ * @param hmmc: Pointer MMC handle
+ * @param pData: Pointer to the buffer that will contain the received data
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Number of blocks to read.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t add = BlockAdd;
+
+ if(NULL == pData)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ /* Initialize data control register */
+ hmmc->Instance->DCTRL = 0U;
+
+ hmmc->pRxBuffPtr = pData;
+ hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
+
+ if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the MMC DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hmmc->Instance, &config);
+
+ __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
+ hmmc->Instance->IDMABASE0 = (uint32_t) pData ;
+ hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
+
+ /* Read Blocks in DMA mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
+
+ /* Read Multi Block command */
+ errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
+ }
+ else
+ {
+ hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
+
+ /* Read Single Block command */
+ errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
+ }
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode = errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Enable transfer interrupts */
+ __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Writes block(s) to a specified address in a card. The Data transfer
+ * is managed by DMA mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_MMC_GetCardState().
+ * @note You could also check the DMA transfer process through the MMC Tx
+ * interrupt event.
+ * @param hmmc: Pointer to MMC handle
+ * @param pData: Pointer to the buffer that will contain the data to transmit
+ * @param BlockAdd: Block Address where data will be written
+ * @param NumberOfBlocks: Number of blocks to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t add = BlockAdd;
+
+ if(NULL == pData)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+
+ if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ /* Initialize data control register */
+ hmmc->Instance->DCTRL = 0U;
+
+ hmmc->pTxBuffPtr = pData;
+ hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
+
+ if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the MMC DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hmmc->Instance, &config);
+
+ __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
+
+ hmmc->Instance->IDMABASE0 = (uint32_t) pData ;
+ hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
+
+ /* Write Blocks in Polling mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
+
+ /* Write Multi Block command */
+ errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
+ }
+ else
+ {
+ hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
+
+ /* Write Single Block command */
+ errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
+ }
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Enable transfer interrupts */
+ __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Erases the specified memory area of the given MMC card.
+ * @note This API should be followed by a check on the card state through
+ * HAL_MMC_GetCardState().
+ * @param hmmc: Pointer to MMC handle
+ * @param BlockStartAdd: Start Block address
+ * @param BlockEndAdd: End Block address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
+{
+ uint32_t errorstate;
+ uint32_t start_add = BlockStartAdd;
+ uint32_t end_add = BlockEndAdd;
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+
+ if(end_add < start_add)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(end_add > (hmmc->MmcCard.LogBlockNbr))
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ /* Check if the card command class supports erase command */
+ if(((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ if((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
+ {
+ start_add *= 512U;
+ end_add *= 512U;
+ }
+
+ /* Send CMD35 MMC_ERASE_GRP_START with argument as addr */
+ errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Send CMD36 MMC_ERASE_GRP_END with argument as addr */
+ errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Send CMD38 ERASE */
+ errorstate = SDMMC_CmdErase(hmmc->Instance);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ hmmc->State = HAL_MMC_STATE_READY;
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief This function handles MMC card interrupt request.
+ * @param hmmc: Pointer to MMC handle
+ * @retval None
+ */
+void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
+{
+ uint32_t errorstate;
+ uint32_t context = hmmc->Context;
+
+ /* Check for SDMMC interrupt flags */
+ if((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
+ {
+ MMC_Read_IT(hmmc);
+ }
+
+ else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) != RESET)
+ {
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DATAEND);
+
+ __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT |\
+ SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR | SDMMC_IT_TXFIFOHE |\
+ SDMMC_IT_RXFIFOHF);
+
+ __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC);
+ __SDMMC_CMDTRANS_DISABLE( hmmc->Instance);
+
+ if((context & MMC_CONTEXT_DMA) != 0U)
+ {
+ hmmc->Instance->DLEN = 0;
+ hmmc->Instance->DCTRL = 0;
+ hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA ;
+
+ /* Stop Transfer for Write Multi blocks or Read Multi blocks */
+ if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
+ {
+ errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->ErrorCallback(hmmc);
+#else
+ HAL_MMC_ErrorCallback(hmmc);
+#endif
+ }
+ }
+
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
+
+ hmmc->State = HAL_MMC_STATE_READY;
+ if(((context & MMC_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
+ {
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->TxCpltCallback(hmmc);
+#else
+ HAL_MMC_TxCpltCallback(hmmc);
+#endif
+ }
+ if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
+ {
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->RxCpltCallback(hmmc);
+#else
+ HAL_MMC_RxCpltCallback(hmmc);
+#endif
+ }
+ }
+ else if((context & MMC_CONTEXT_IT) != 0U)
+ {
+ /* Stop Transfer for Write Multi blocks or Read Multi blocks */
+ if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
+ {
+ errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->ErrorCallback(hmmc);
+#else
+ HAL_MMC_ErrorCallback(hmmc);
+#endif
+ }
+ }
+
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
+
+ hmmc->State = HAL_MMC_STATE_READY;
+ if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
+ {
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->RxCpltCallback(hmmc);
+#else
+ HAL_MMC_RxCpltCallback(hmmc);
+#endif
+ }
+ else
+ {
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->TxCpltCallback(hmmc);
+#else
+ HAL_MMC_TxCpltCallback(hmmc);
+#endif
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+
+ else if((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
+ {
+ MMC_Write_IT(hmmc);
+ }
+
+ else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL| SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_RXOVERR | SDMMC_FLAG_TXUNDERR) != RESET)
+ {
+ /* Set Error code */
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DCRCFAIL) != RESET)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
+ }
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DTIMEOUT) != RESET)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
+ }
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_RXOVERR) != RESET)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
+ }
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_TXUNDERR) != RESET)
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
+ }
+
+ /* Clear All flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
+
+ /* Disable all interrupts */
+ __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
+ SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
+
+ __SDMMC_CMDTRANS_DISABLE( hmmc->Instance);
+ hmmc->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
+ hmmc->Instance->CMD |= SDMMC_CMD_CMDSTOP;
+ hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
+ hmmc->Instance->CMD &= ~(SDMMC_CMD_CMDSTOP);
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DABORT);
+
+ if((context & MMC_CONTEXT_IT) != 0U)
+ {
+ /* Set the MMC state to ready to be able to start again the process */
+ hmmc->State = HAL_MMC_STATE_READY;
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->ErrorCallback(hmmc);
+#else
+ HAL_MMC_ErrorCallback(hmmc);
+#endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
+ }
+ else if((context & MMC_CONTEXT_DMA) != 0U)
+ {
+ if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
+ {
+ /* Disable Internal DMA */
+ __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC);
+ hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
+
+ /* Set the MMC state to ready to be able to start again the process */
+ hmmc->State = HAL_MMC_STATE_READY;
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->ErrorCallback(hmmc);
+#else
+ HAL_MMC_ErrorCallback(hmmc);
+#endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+
+ else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_IDMABTC) != RESET)
+ {
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_IT_IDMABTC);
+ if(READ_BIT(hmmc->Instance->IDMACTRL, SDMMC_IDMA_IDMABACT) == 0U)
+ {
+ /* Current buffer is buffer0, Transfer complete for buffer1 */
+ if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
+ {
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->Write_DMADblBuf1CpltCallback(hmmc);
+#else
+ HAL_MMCEx_Write_DMADoubleBuf1CpltCallback(hmmc);
+#endif
+ }
+ else /* MMC_CONTEXT_READ_MULTIPLE_BLOCK */
+ {
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->Read_DMADblBuf1CpltCallback(hmmc);
+#else
+ HAL_MMCEx_Read_DMADoubleBuf1CpltCallback(hmmc);
+#endif
+ }
+ }
+ else /* MMC_DMA_BUFFER1 */
+ {
+ /* Current buffer is buffer1, Transfer complete for buffer0 */
+ if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
+ {
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->Write_DMADblBuf0CpltCallback(hmmc);
+#else
+ HAL_MMCEx_Write_DMADoubleBuf0CpltCallback(hmmc);
+#endif
+ }
+ else /* MMC_CONTEXT_READ_MULTIPLE_BLOCK */
+ {
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->Read_DMADblBuf0CpltCallback(hmmc);
+#else
+ HAL_MMCEx_Read_DMADoubleBuf0CpltCallback(hmmc);
+#endif
+ }
+ }
+ }
+
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief return the MMC state
+ * @param hmmc: Pointer to mmc handle
+ * @retval HAL state
+ */
+HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
+{
+ return hmmc->State;
+}
+
+/**
+* @brief Return the MMC error code
+* @param hmmc : Pointer to a MMC_HandleTypeDef structure that contains
+ * the configuration information.
+* @retval MMC Error Code
+*/
+uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
+{
+ return hmmc->ErrorCode;
+}
+
+/**
+ * @brief Tx Transfer completed callbacks
+ * @param hmmc: Pointer to MMC handle
+ * @retval None
+ */
+__weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MMC_TxCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callbacks
+ * @param hmmc: Pointer MMC handle
+ * @retval None
+ */
+__weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MMC_RxCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief MMC error callbacks
+ * @param hmmc: Pointer MMC handle
+ * @retval None
+ */
+__weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MMC_ErrorCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief MMC Abort callbacks
+ * @param hmmc: Pointer MMC handle
+ * @retval None
+ */
+__weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MMC_AbortCallback can be implemented in the user file
+ */
+}
+
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+/**
+ * @brief Register a User MMC Callback
+ * To be used instead of the weak (surcharged) predefined callback
+ * @param hmmc : MMC handle
+ * @param CallbackId : ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
+ * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
+ * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
+ * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
+ * @arg @ref HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Rx Double buffer 0 Callback ID
+ * @arg @ref HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Rx Double buffer 1 Callback ID
+ * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Tx Double buffer 0 Callback ID
+ * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Tx Double buffer 1 Callback ID
+ * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
+ * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmmc);
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ switch (CallbackId)
+ {
+ case HAL_MMC_TX_CPLT_CB_ID :
+ hmmc->TxCpltCallback = pCallback;
+ break;
+ case HAL_MMC_RX_CPLT_CB_ID :
+ hmmc->RxCpltCallback = pCallback;
+ break;
+ case HAL_MMC_ERROR_CB_ID :
+ hmmc->ErrorCallback = pCallback;
+ break;
+ case HAL_MMC_ABORT_CB_ID :
+ hmmc->AbortCpltCallback = pCallback;
+ break;
+ case HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID :
+ hmmc->Read_DMADblBuf0CpltCallback = pCallback;
+ break;
+ case HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID :
+ hmmc->Read_DMADblBuf1CpltCallback = pCallback;
+ break;
+ case HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID :
+ hmmc->Write_DMADblBuf0CpltCallback = pCallback;
+ break;
+ case HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID :
+ hmmc->Write_DMADblBuf1CpltCallback = pCallback;
+ break;
+ case HAL_MMC_MSP_INIT_CB_ID :
+ hmmc->MspInitCallback = pCallback;
+ break;
+ case HAL_MMC_MSP_DEINIT_CB_ID :
+ hmmc->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hmmc->State == HAL_MMC_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_MMC_MSP_INIT_CB_ID :
+ hmmc->MspInitCallback = pCallback;
+ break;
+ case HAL_MMC_MSP_DEINIT_CB_ID :
+ hmmc->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmmc);
+ return status;
+}
+
+/**
+ * @brief Unregister a User MMC Callback
+ * MMC Callback is redirected to the weak (surcharged) predefined callback
+ * @param hmmc : MMC handle
+ * @param CallbackId : ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
+ * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
+ * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
+ * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
+ * @arg @ref HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Rx Double buffer 0 Callback ID
+ * @arg @ref HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Rx Double buffer 1 Callback ID
+ * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Tx Double buffer 0 Callback ID
+ * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Tx Double buffer 1 Callback ID
+ * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
+ * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hmmc);
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ switch (CallbackId)
+ {
+ case HAL_MMC_TX_CPLT_CB_ID :
+ hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
+ break;
+ case HAL_MMC_RX_CPLT_CB_ID :
+ hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
+ break;
+ case HAL_MMC_ERROR_CB_ID :
+ hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
+ break;
+ case HAL_MMC_ABORT_CB_ID :
+ hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
+ break;
+ case HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID :
+ hmmc->Read_DMADblBuf0CpltCallback = HAL_MMCEx_Read_DMADoubleBuf0CpltCallback;
+ break;
+ case HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID :
+ hmmc->Read_DMADblBuf1CpltCallback = HAL_MMCEx_Read_DMADoubleBuf1CpltCallback;
+ break;
+ case HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID :
+ hmmc->Write_DMADblBuf0CpltCallback = HAL_MMCEx_Write_DMADoubleBuf0CpltCallback;
+ break;
+ case HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID :
+ hmmc->Write_DMADblBuf1CpltCallback = HAL_MMCEx_Write_DMADoubleBuf1CpltCallback;
+ break;
+ case HAL_MMC_MSP_INIT_CB_ID :
+ hmmc->MspInitCallback = HAL_MMC_MspInit;
+ break;
+ case HAL_MMC_MSP_DEINIT_CB_ID :
+ hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hmmc->State == HAL_MMC_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_MMC_MSP_INIT_CB_ID :
+ hmmc->MspInitCallback = HAL_MMC_MspInit;
+ break;
+ case HAL_MMC_MSP_DEINIT_CB_ID :
+ hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmmc);
+ return status;
+}
+#endif
+
+/**
+ * @}
+ */
+
+/** @addtogroup MMC_Exported_Functions_Group3
+ * @brief management functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the MMC card
+ operations and get the related information
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns information the information of the card which are stored on
+ * the CID register.
+ * @param hmmc: Pointer to MMC handle
+ * @param pCID: Pointer to a HAL_MMC_CIDTypedef structure that
+ * contains all CID register parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
+{
+ pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U);
+
+ pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U);
+
+ pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U));
+
+ pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU);
+
+ pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U);
+
+ pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U));
+
+ pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U);
+
+ pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U);
+
+ pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U);
+
+ pCID->Reserved2 = 1U;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Returns information the information of the card which are stored on
+ * the CSD register.
+ * @param hmmc: Pointer to MMC handle
+ * @param pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that
+ * contains all CSD register parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
+{
+ uint32_t block_nbr = 0;
+
+ pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
+
+ pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
+
+ pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
+
+ pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
+
+ pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
+
+ pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
+
+ pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
+
+ pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
+
+ pCSD->PartBlockRead = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
+
+ pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
+
+ pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
+
+ pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
+
+ pCSD->Reserved2 = 0U; /*!< Reserved */
+
+ if(MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */
+ {
+ return HAL_ERROR;
+ }
+
+ if(hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD)
+ {
+ pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
+
+ pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
+
+ pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
+
+ pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
+
+ pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
+
+ pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
+
+ hmmc->MmcCard.BlockNbr = (pCSD->DeviceSize + 1U) ;
+ hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
+ hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
+
+ hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);
+ hmmc->MmcCard.LogBlockSize = 512U;
+ }
+ else if(hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD)
+ {
+ hmmc->MmcCard.BlockNbr = block_nbr;
+ hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr;
+ hmmc->MmcCard.BlockSize = 512U;
+ hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize;
+ }
+ else
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
+
+ pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
+
+ pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
+
+ pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
+
+ pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
+
+ pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
+
+ pCSD->MaxWrBlockLen= (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
+
+ pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
+
+ pCSD->Reserved3 = 0;
+
+ pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
+
+ pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
+
+ pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
+
+ pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
+
+ pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
+
+ pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
+
+ pCSD->ECC= (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
+
+ pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
+
+ pCSD->Reserved4 = 1;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Gets the MMC card info.
+ * @param hmmc: Pointer to MMC handle
+ * @param pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that
+ * will contain the MMC card status information
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
+{
+ pCardInfo->CardType = (uint32_t)(hmmc->MmcCard.CardType);
+ pCardInfo->Class = (uint32_t)(hmmc->MmcCard.Class);
+ pCardInfo->RelCardAdd = (uint32_t)(hmmc->MmcCard.RelCardAdd);
+ pCardInfo->BlockNbr = (uint32_t)(hmmc->MmcCard.BlockNbr);
+ pCardInfo->BlockSize = (uint32_t)(hmmc->MmcCard.BlockSize);
+ pCardInfo->LogBlockNbr = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
+ pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables wide bus operation for the requested card if supported by
+ * card.
+ * @param hmmc: Pointer to MMC handle
+ * @param WideMode: Specifies the MMC card wide bus mode
+ * This parameter can be one of the following values:
+ * @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer
+ * @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer
+ * @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
+{
+ __IO uint32_t count = 0U;
+ SDMMC_InitTypeDef Init;
+ uint32_t errorstate;
+ uint32_t response = 0U, busy = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_BUS_WIDE(WideMode));
+
+ /* Chnage Satte */
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ if(WideMode == SDMMC_BUS_WIDE_8B)
+ {
+ errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ }
+ else if(WideMode == SDMMC_BUS_WIDE_4B)
+ {
+ errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ }
+ else if(WideMode == SDMMC_BUS_WIDE_1B)
+ {
+ errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ }
+ else
+ {
+ /* WideMode is not a valid argument*/
+ hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+ }
+
+ /* Check for switch error and violation of the trial number of sending CMD 13 */
+ while(busy == 0U)
+ {
+ if(count == SDMMC_MAX_TRIAL)
+ {
+ hmmc->State = HAL_MMC_STATE_READY;
+ hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
+ return HAL_ERROR;
+ }
+ count++;
+
+ /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
+ errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+
+ /* Get command response */
+ response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+
+ /* Get operating voltage*/
+ busy = (((response >> 7U) == 1U) ? 0U : 1U);
+ }
+
+ /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
+ count = SDMMC_DATATIMEOUT;
+ while((response & 0x00000100U) == 0U)
+ {
+ if(count == 0U)
+ {
+ hmmc->State = HAL_MMC_STATE_READY;
+ hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
+ return HAL_ERROR;
+ }
+ count--;
+
+ /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
+ errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+
+ /* Get command response */
+ response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+ }
+
+ if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Configure the SDMMC peripheral */
+ Init.ClockEdge = hmmc->Init.ClockEdge;
+ Init.ClockPowerSave = hmmc->Init.ClockPowerSave;
+ Init.BusWide = WideMode;
+ Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
+ Init.ClockDiv = hmmc->Init.ClockDiv;
+ (void)SDMMC_Init(hmmc->Instance, Init);
+ }
+
+ /* Change State */
+ hmmc->State = HAL_MMC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the speed bus mode
+ * @param hmmc: Pointer to the MMC handle
+ * @param SpeedMode: Specifies the MMC card speed bus mode
+ * This parameter can be one of the following values:
+ * @arg SDMMC_SPEED_MODE_AUTO: Max speed mode supported by the card
+ * @arg SDMMC_SPEED_MODE_DEFAULT: Default Speed (MMC @ 26MHz)
+ * @arg SDMMC_SPEED_MODE_HIGH: High Speed (MMC @ 52 MHz)
+ * @arg SDMMC_SPEED_MODE_DDR: High Speed DDR (MMC DDR @ 52 MHz)
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_MMC_ConfigSpeedBusOperation(MMC_HandleTypeDef *hmmc, uint32_t SpeedMode)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t device_type;
+ uint32_t errorstate;
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_SPEED_MODE(SpeedMode));
+ /* Change State */
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ if(MMC_ReadExtCSD(hmmc, &device_type, 196, 0x0FFFFFFFU) != HAL_OK) /* Field DEVICE_TYPE [196] */
+ {
+ return HAL_ERROR;
+ }
+
+ switch (SpeedMode)
+ {
+ case SDMMC_SPEED_MODE_AUTO:
+ {
+ if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U))
+ {
+ /* High Speed DDR mode allowed */
+ errorstate = MMC_HighSpeed(hmmc, ENABLE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ else
+ {
+ errorstate = MMC_DDR_Mode(hmmc, ENABLE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ }
+ }
+ else if ((device_type & 0x02U) != 0U)
+ {
+ /* High Speed mode allowed */
+ errorstate = MMC_HighSpeed(hmmc, ENABLE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ }
+ else
+ {
+ /* Nothing to do : keep current speed */
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_DDR:
+ {
+ if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U))
+ {
+ /* High Speed DDR mode allowed */
+ errorstate = MMC_HighSpeed(hmmc, ENABLE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ else
+ {
+ errorstate = MMC_DDR_Mode(hmmc, ENABLE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ }
+ }
+ else
+ {
+ /* High Speed DDR mode not allowed */
+ hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_HIGH:
+ {
+ if ((device_type & 0x02U) != 0U)
+ {
+ /* High Speed mode allowed */
+ errorstate = MMC_HighSpeed(hmmc, ENABLE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ }
+ else
+ {
+ /* High Speed mode not allowed */
+ hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_DEFAULT:
+ {
+ if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U)
+ {
+ /* High Speed DDR mode activated */
+ errorstate = MMC_DDR_Mode(hmmc, DISABLE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ }
+ if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U)
+ {
+ /* High Speed mode activated */
+ errorstate = MMC_HighSpeed(hmmc, DISABLE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+ }
+ break;
+ }
+ default:
+ hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+ status = HAL_ERROR;
+ break;
+ }
+
+ /* Verify that MMC card is ready to use after Speed mode switch*/
+ tickstart = HAL_GetTick();
+ while ((HAL_MMC_GetCardState(hmmc) != HAL_MMC_CARD_TRANSFER))
+ {
+ if ((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
+ {
+ hmmc->ErrorCode = HAL_MMC_ERROR_TIMEOUT;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Change State */
+ hmmc->State = HAL_MMC_STATE_READY;
+ return status;
+}
+
+/**
+ * @brief Gets the current mmc card data state.
+ * @param hmmc: pointer to MMC handle
+ * @retval Card state
+ */
+HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
+{
+ uint32_t cardstate;
+ uint32_t errorstate;
+ uint32_t resp1 = 0U;
+
+ errorstate = MMC_SendStatus(hmmc, &resp1);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+
+ cardstate = ((resp1 >> 9U) & 0x0FU);
+
+ return (HAL_MMC_CardStateTypeDef)cardstate;
+}
+
+/**
+ * @brief Abort the current transfer and disable the MMC.
+ * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
+ * the configuration information for MMC module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
+{
+ HAL_MMC_CardStateTypeDef CardState;
+
+ /* DIsable All interrupts */
+ __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
+ SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
+
+ /* Clear All flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
+
+ /* If IDMA Context, disable Internal DMA */
+ hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
+
+ hmmc->State = HAL_MMC_STATE_READY;
+
+ /* Initialize the MMC operation */
+ hmmc->Context = MMC_CONTEXT_NONE;
+
+ CardState = HAL_MMC_GetCardState(hmmc);
+ if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
+ {
+ hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
+ }
+ if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort the current transfer and disable the MMC (IT mode).
+ * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
+ * the configuration information for MMC module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
+{
+ HAL_MMC_CardStateTypeDef CardState;
+
+ /* DIsable All interrupts */
+ __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
+ SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
+
+ /* If IDMA Context, disable Internal DMA */
+ hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
+
+ /* Clear All flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
+
+ CardState = HAL_MMC_GetCardState(hmmc);
+ hmmc->State = HAL_MMC_STATE_READY;
+
+ if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
+ {
+ hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
+ }
+ if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
+ hmmc->AbortCpltCallback(hmmc);
+#else
+ HAL_MMC_AbortCallback(hmmc);
+#endif
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private function ----------------------------------------------------------*/
+/** @addtogroup MMC_Private_Functions
+ * @{
+ */
+
+
+/**
+ * @brief Initializes the mmc card.
+ * @param hmmc: Pointer to MMC handle
+ * @retval MMC Card error state
+ */
+static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
+{
+ HAL_MMC_CardCSDTypeDef CSD;
+ uint32_t errorstate;
+ uint16_t mmc_rca = 1U;
+ MMC_InitTypeDef Init;
+
+ /* Check the power State */
+ if(SDMMC_GetPowerState(hmmc->Instance) == 0U)
+ {
+ /* Power off */
+ return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
+ }
+
+ /* Send CMD2 ALL_SEND_CID */
+ errorstate = SDMMC_CmdSendCID(hmmc->Instance);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ return errorstate;
+ }
+ else
+ {
+ /* Get Card identification number data */
+ hmmc->CID[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+ hmmc->CID[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
+ hmmc->CID[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
+ hmmc->CID[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
+ }
+
+ /* Send CMD3 SET_REL_ADDR with argument 0 */
+ /* MMC Card publishes its RCA. */
+ errorstate = SDMMC_CmdSetRelAdd(hmmc->Instance, &mmc_rca);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Get the MMC card RCA */
+ hmmc->MmcCard.RelCardAdd = mmc_rca;
+
+ /* Send CMD9 SEND_CSD with argument as card's RCA */
+ errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ return errorstate;
+ }
+ else
+ {
+ /* Get Card Specific Data */
+ hmmc->CSD[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+ hmmc->CSD[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
+ hmmc->CSD[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
+ hmmc->CSD[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
+ }
+
+ /* Get the Card Class */
+ hmmc->MmcCard.Class = (SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2) >> 20U);
+
+ /* Select the Card */
+ errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Get CSD parameters */
+ if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
+ {
+ return hmmc->ErrorCode;
+ }
+
+ /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
+ errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+
+ /* Configure the SDMMC peripheral */
+ Init.ClockEdge = hmmc->Init.ClockEdge;
+ Init.ClockPowerSave = hmmc->Init.ClockPowerSave;
+ Init.BusWide = SDMMC_BUS_WIDE_1B;
+ Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
+ Init.ClockDiv = hmmc->Init.ClockDiv;
+ (void)SDMMC_Init(hmmc->Instance, Init);
+
+ /* All cards are initialized */
+ return HAL_MMC_ERROR_NONE;
+}
+
+/**
+ * @brief Enquires cards about their operating voltage and configures clock
+ * controls and stores MMC information that will be needed in future
+ * in the MMC handle.
+ * @param hmmc: Pointer to MMC handle
+ * @retval error state
+ */
+static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
+{
+ __IO uint32_t count = 0U;
+ uint32_t response = 0U, validvoltage = 0U;
+ uint32_t errorstate;
+
+ /* CMD0: GO_IDLE_STATE */
+ errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ while(validvoltage == 0U)
+ {
+ if(count++ == SDMMC_MAX_VOLT_TRIAL)
+ {
+ return HAL_MMC_ERROR_INVALID_VOLTRANGE;
+ }
+
+ /* SEND CMD1 APP_CMD with MMC_HIGH_VOLTAGE_RANGE(0xC0FF8000) as argument */
+ errorstate = SDMMC_CmdOpCondition(hmmc->Instance, eMMC_HIGH_VOLTAGE_RANGE);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
+ }
+
+ /* Get command response */
+ response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+
+ /* Get operating voltage*/
+ validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
+ }
+
+ /* When power routine is finished and command returns valid voltage */
+ if (((response & (0xFF000000U)) >> 24) == 0xC0U)
+ {
+ hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD;
+ }
+ else
+ {
+ hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD;
+ }
+
+ return HAL_MMC_ERROR_NONE;
+}
+
+/**
+ * @brief Turns the SDMMC output signals off.
+ * @param hmmc: Pointer to MMC handle
+ * @retval None
+ */
+static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
+{
+ /* Set Power State to OFF */
+ (void)SDMMC_PowerState_OFF(hmmc->Instance);
+}
+
+/**
+ * @brief Returns the current card's status.
+ * @param hmmc: Pointer to MMC handle
+ * @param pCardStatus: pointer to the buffer that will contain the MMC card
+ * status (Card Status register)
+ * @retval error state
+ */
+static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
+{
+ uint32_t errorstate;
+
+ if(pCardStatus == NULL)
+ {
+ return HAL_MMC_ERROR_PARAM;
+ }
+
+ /* Send Status command */
+ errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Get MMC card status */
+ *pCardStatus = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+
+ return HAL_MMC_ERROR_NONE;
+}
+
+/**
+ * @brief Reads extended CSD register to get the sectors number of the device
+ * @param hmmc: Pointer to MMC handle
+ * @param pFieldData: Pointer to the read buffer
+ * @param FieldIndex: Index of the field to be read
+ * @param Timeout: Specify timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t count;
+ uint32_t i = 0;
+ uint32_t tmp_data;
+
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+
+ /* Initialize data control register */
+ hmmc->Instance->DCTRL = 0;
+
+ /* Configure the MMC DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = 512;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_ENABLE;
+ (void)SDMMC_ConfigData(hmmc->Instance, &config);
+
+ /* Set Block Size for Card */
+ errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= errorstate;
+ hmmc->State = HAL_MMC_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Poll on SDMMC flags */
+ while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
+ {
+ if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF))
+ {
+ /* Read data from SDMMC Rx FIFO */
+ for(count = 0U; count < 8U; count++)
+ {
+ tmp_data = SDMMC_ReadFIFO(hmmc->Instance);
+ /* eg : SEC_COUNT : FieldIndex = 212 => i+count = 53 */
+ /* DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */
+ if ((i + count) == ((uint32_t)FieldIndex/4U))
+ {
+ *pFieldData = tmp_data;
+ }
+ }
+ i += 8U;
+ }
+
+ if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
+ {
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+ hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
+ hmmc->State= HAL_MMC_STATE_READY;
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
+ errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->ErrorCode |= errorstate;
+ }
+
+ /* Clear all the static flags */
+ __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
+
+ hmmc->State = HAL_MMC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Wrap up reading in non-blocking mode.
+ * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
+ * the configuration information.
+ * @retval None
+ */
+static void MMC_Read_IT(MMC_HandleTypeDef *hmmc)
+{
+ uint32_t count, data;
+ uint8_t* tmp;
+
+ tmp = hmmc->pRxBuffPtr;
+
+ if (hmmc->RxXferSize >= 32U)
+ {
+ /* Read data from SDMMC Rx FIFO */
+ for(count = 0U; count < 8U; count++)
+ {
+ data = SDMMC_ReadFIFO(hmmc->Instance);
+ *tmp = (uint8_t)(data & 0xFFU);
+ tmp++;
+ *tmp = (uint8_t)((data >> 8U) & 0xFFU);
+ tmp++;
+ *tmp = (uint8_t)((data >> 16U) & 0xFFU);
+ tmp++;
+ *tmp = (uint8_t)((data >> 24U) & 0xFFU);
+ tmp++;
+ }
+
+ hmmc->pRxBuffPtr = tmp;
+ hmmc->RxXferSize -= 32U;
+ }
+}
+
+/**
+ * @brief Wrap up writing in non-blocking mode.
+ * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
+ * the configuration information.
+ * @retval None
+ */
+static void MMC_Write_IT(MMC_HandleTypeDef *hmmc)
+{
+ uint32_t count, data;
+ uint8_t* tmp;
+
+ tmp = hmmc->pTxBuffPtr;
+
+ if (hmmc->TxXferSize >= 32U)
+ {
+ /* Write data to SDMMC Tx FIFO */
+ for(count = 0U; count < 8U; count++)
+ {
+ data = (uint32_t)(*tmp);
+ tmp++;
+ data |= ((uint32_t)(*tmp) << 8U);
+ tmp++;
+ data |= ((uint32_t)(*tmp) << 16U);
+ tmp++;
+ data |= ((uint32_t)(*tmp) << 24U);
+ tmp++;
+ (void)SDMMC_WriteFIFO(hmmc->Instance, &data);
+ }
+
+ hmmc->pTxBuffPtr = tmp;
+ hmmc->TxXferSize -= 32U;
+ }
+}
+
+/**
+ * @brief Switches the MMC card to high speed mode.
+ * @param hmmc: MMC handle
+ * @param state: State of high speed mode
+ * @retval MMC Card error state
+ */
+static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state)
+{
+ uint32_t errorstate = HAL_MMC_ERROR_NONE;
+ uint32_t response, count;
+ SDMMC_InitTypeDef Init;
+
+ if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U) && (state == DISABLE))
+ {
+ /* Index : 185 - Value : 0 */
+ errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90000U);
+ }
+
+ if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) == 0U) && (state != DISABLE))
+ {
+ /* Index : 185 - Value : 1 */
+ errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90100U);
+ }
+
+ if(errorstate == HAL_MMC_ERROR_NONE)
+ {
+ /* Check for switch error */
+ errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+ if(errorstate == HAL_MMC_ERROR_NONE)
+ {
+ /* Get command response */
+ response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+ if ((response & 0x80U) != 0U)
+ {
+ errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
+ }
+ else
+ {
+ /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
+ count = SDMMC_MAX_TRIAL;
+ while(((response & 0x100U) == 0U) && (count != 0U))
+ {
+ count--;
+
+ errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ break;
+ }
+
+ /* Get command response */
+ response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+ }
+
+ /* Configure high speed */
+ if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
+ {
+ Init.ClockEdge = hmmc->Init.ClockEdge;
+ Init.ClockPowerSave = hmmc->Init.ClockPowerSave;
+ Init.BusWide = (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS);
+ Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
+
+ if (state == DISABLE)
+ {
+ Init.ClockDiv = hmmc->Init.ClockDiv;
+ (void)SDMMC_Init(hmmc->Instance, Init);
+
+ CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED);
+ }
+ else
+ {
+ Init.ClockDiv = SDMMC_HSpeed_CLK_DIV;
+ (void)SDMMC_Init(hmmc->Instance, Init);
+
+ SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED);
+ }
+ }
+ }
+ }
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Switches the MMC card to Double Data Rate (DDR) mode.
+ * @param hmmc: MMC handle
+ * @param state: State of DDR mode
+ * @retval MMC Card error state
+ */
+static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state)
+{
+ uint32_t errorstate = HAL_MMC_ERROR_NONE;
+ uint32_t response, count;
+
+ if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U) && (state == DISABLE))
+ {
+ if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U)
+ {
+ /* Index : 183 - Value : 1 */
+ errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
+ }
+ else
+ {
+ /* Index : 183 - Value : 2 */
+ errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
+ }
+ }
+
+ if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) == 0U) && (state != DISABLE))
+ {
+ if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U)
+ {
+ /* Index : 183 - Value : 5 */
+ errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70500U);
+ }
+ else
+ {
+ /* Index : 183 - Value : 6 */
+ errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70600U);
+ }
+ }
+
+ if(errorstate == HAL_MMC_ERROR_NONE)
+ {
+ /* Check for switch error */
+ errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+ if(errorstate == HAL_MMC_ERROR_NONE)
+ {
+ /* Get command response */
+ response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+ if ((response & 0x80U) != 0U)
+ {
+ errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
+ }
+ else
+ {
+ /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
+ count = SDMMC_MAX_TRIAL;
+ while(((response & 0x100U) == 0U) && (count != 0U))
+ {
+ count--;
+
+ errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ break;
+ }
+
+ /* Get command response */
+ response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
+ }
+
+ /* Configure DDR mode */
+ if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
+ {
+ if (state == DISABLE)
+ {
+ CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR);
+ }
+ else
+ {
+ SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR);
+ }
+ }
+ }
+ }
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Read DMA Buffer 0 Transfer completed callbacks
+ * @param hmmc: MMC handle
+ * @retval None
+ */
+__weak void HAL_MMCEx_Read_DMADoubleBuf0CpltCallback(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MMCEx_Read_DMADoubleBuf0CpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Read DMA Buffer 1 Transfer completed callbacks
+ * @param hmmc: MMC handle
+ * @retval None
+ */
+__weak void HAL_MMCEx_Read_DMADoubleBuf1CpltCallback(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MMCEx_Read_DMADoubleBuf1CpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Write DMA Buffer 0 Transfer completed callbacks
+ * @param hmmc: MMC handle
+ * @retval None
+ */
+__weak void HAL_MMCEx_Write_DMADoubleBuf0CpltCallback(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MMCEx_Write_DMADoubleBuf0CpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Write DMA Buffer 1 Transfer completed callbacks
+ * @param hmmc: MMC handle
+ * @retval None
+ */
+__weak void HAL_MMCEx_Write_DMADoubleBuf1CpltCallback(MMC_HandleTypeDef *hmmc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmmc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MMCEx_Write_DMADoubleBuf1CpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_MMC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_mmc_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mmc_ex.c
new file mode 100644
index 0000000000..8b4d18eafe
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_mmc_ex.c
@@ -0,0 +1,304 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_mmc_ex.c
+ * @author MCD Application Team
+ * @brief MMC card Extended HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Secure Digital (MMC) peripheral:
+ * + Extended features functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The MMC Extension HAL driver can be used as follows:
+ (+) Configure Buffer0 and Buffer1 start address and Buffer size using HAL_MMCEx_ConfigDMAMultiBuffer() function.
+
+ (+) Start Read and Write for multibuffer mode using HAL_MMCEx_ReadBlocksDMAMultiBuffer() and HAL_MMCEx_WriteBlocksDMAMultiBuffer() functions.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup MMCEx MMCEx
+ * @brief MMC Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_MMC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup MMCEx_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup MMCEx_Exported_Functions_Group1
+ * @brief Multibuffer functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Multibuffer functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to configure the multibuffer mode and start read and write
+ multibuffer mode for MMC HAL driver.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure DMA Dual Buffer mode. The Data transfer is managed by an Internal DMA.
+ * @param hmmc: MMC handle
+ * @param pDataBuffer0: Pointer to the buffer0 that will contain/receive the transfered data
+ * @param pDataBuffer1: Pointer to the buffer1 that will contain/receive the transfered data
+ * @param BufferSize: Size of Buffer0 in Blocks. Buffer0 and Buffer1 must have the same size.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMCEx_ConfigDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t * pDataBuffer0, uint32_t * pDataBuffer1, uint32_t BufferSize)
+{
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ hmmc->Instance->IDMABASE0= (uint32_t) pDataBuffer0 ;
+ hmmc->Instance->IDMABASE1= (uint32_t) pDataBuffer1 ;
+ hmmc->Instance->IDMABSIZE= (uint32_t) (MMC_BLOCKSIZE * BufferSize);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The received Data will be stored in Buffer0 and Buffer1.
+ * Buffer0, Buffer1 and BufferSize need to be configured by function HAL_MMCEx_ConfigDMAMultiBuffer before call this function.
+ * @param hmmc: MMC handle
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Total number of blocks to read
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMCEx_ReadBlocksDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t DmaBase0_reg, DmaBase1_reg;
+ uint32_t errorstate;
+ uint32_t add = BlockAdd;
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ DmaBase0_reg = hmmc->Instance->IDMABASE0;
+ DmaBase1_reg = hmmc->Instance->IDMABASE1;
+ if ((hmmc->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
+ {
+ hmmc->ErrorCode = HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ /* Initialize data control register */
+ hmmc->Instance->DCTRL = 0;
+
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the MMC DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hmmc->Instance, &config);
+
+ hmmc->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
+
+ __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
+
+ hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
+
+ /* Read Blocks in DMA mode */
+ hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
+
+ /* Read Multi Block command */
+ errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->State = HAL_MMC_STATE_READY;
+ hmmc->ErrorCode |= errorstate;
+ return HAL_ERROR;
+ }
+
+ __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | SDMMC_FLAG_IDMATE | SDMMC_FLAG_IDMABTC));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+}
+
+/**
+ * @brief Write block(s) to a specified address in a card. The transfered Data are stored in Buffer0 and Buffer1.
+ * Buffer0, Buffer1 and BufferSize need to be configured by function HAL_MMCEx_ConfigDMAMultiBuffer before call this function.
+ * @param hmmc: MMC handle
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Total number of blocks to read
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_MMCEx_WriteBlocksDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t DmaBase0_reg, DmaBase1_reg;
+ uint32_t add = BlockAdd;
+
+ if(hmmc->State == HAL_MMC_STATE_READY)
+ {
+ if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
+ {
+ hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ DmaBase0_reg = hmmc->Instance->IDMABASE0;
+ DmaBase1_reg = hmmc->Instance->IDMABASE1;
+ if ((hmmc->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
+ {
+ hmmc->ErrorCode = HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ /* Initialize data control register */
+ hmmc->Instance->DCTRL = 0;
+
+ hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+
+ hmmc->State = HAL_MMC_STATE_BUSY;
+
+ if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the MMC DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hmmc->Instance, &config);
+
+ __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
+
+ hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
+
+ /* Write Blocks in DMA mode */
+ hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
+
+ /* Write Multi Block command */
+ errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
+ if(errorstate != HAL_MMC_ERROR_NONE)
+ {
+ hmmc->State = HAL_MMC_STATE_READY;
+ hmmc->ErrorCode |= errorstate;
+ return HAL_ERROR;
+ }
+
+ __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_FLAG_IDMATE | SDMMC_FLAG_IDMABTC));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+/**
+ * @brief Change the DMA Buffer0 or Buffer1 address on the fly.
+ * @param hmmc: pointer to a MMC_HandleTypeDef structure.
+ * @param Buffer: the buffer to be changed, This parameter can be one of
+ * the following values: MMC_DMA_BUFFER0 or MMC_DMA_BUFFER1
+ * @param pDataBuffer: The new address
+ * @note The BUFFER0 address can be changed only when the current transfer use
+ * BUFFER1 and the BUFFER1 address can be changed only when the current
+ * transfer use BUFFER0.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MMCEx_ChangeDMABuffer(MMC_HandleTypeDef *hmmc, HAL_MMCEx_DMABuffer_MemoryTypeDef Buffer, uint32_t *pDataBuffer)
+{
+ if(Buffer == MMC_DMA_BUFFER0)
+ {
+ /* change the buffer0 address */
+ hmmc->Instance->IDMABASE0 = (uint32_t)pDataBuffer;
+ }
+ else
+ {
+ /* change the memory1 address */
+ hmmc->Instance->IDMABASE1 = (uint32_t)pDataBuffer;
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_MMC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_nand.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_nand.c
new file mode 100644
index 0000000000..4e593adc02
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_nand.c
@@ -0,0 +1,2183 @@
+/**
+ ******************************************************************************
+ * @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.
+ *
+ @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 @ref 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 @ref HAL_NAND_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) 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 @ref HAL_NAND_Init and if the state is HAL_NAND_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_NAND_Init
+ and @ref HAL_NAND_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_NAND_Init and @ref 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 @ref HAL_NAND_RegisterCallback before calling @ref HAL_NAND_DeInit
+ or @ref 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 (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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
+ }
+
+ /* 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
+
+ /* 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
+
+ /* 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
+
+ /* 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
+
+ /* 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
+
+ /* 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, 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, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceAddress, numPagesRead = 0U, nandAddress, 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)0x00U);
+ __DSB();
+ }
+
+ /* Get Data into Buffer */
+ for (index = 0U; index < hnand->Config.PageSize; index++)
+ {
+ *buff = *(uint8_t *)deviceAddress;
+ buff++;
+ }
+
+ /* Increment read pages number */
+ numPagesRead++;
+
+ /* 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, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumPageToRead)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceAddress, numPagesRead = 0, nandAddress, 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)0x00U);
+ __DSB();
+ }
+
+ /* Get Data into Buffer */
+ for (index = 0U; index < hnand->Config.PageSize; index++)
+ {
+ *buff = *(uint16_t *)deviceAddress;
+ buff++;
+ }
+
+ /* Increment read pages number */
+ numPagesRead++;
+
+ /* 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, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceAddress, numPagesWritten = 0, nandAddress, nbpages = NumPageToWrite;
+ 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;
+ }
+ }
+
+ /* Increment written pages number */
+ numPagesWritten++;
+
+ /* 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, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumPageToWrite)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceAddress, numPagesWritten = 0, nandAddress, nbpages = NumPageToWrite;
+ 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();
+ }
+ }
+
+ /* 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;
+ }
+ }
+
+ /* Increment written pages number */
+ numPagesWritten++;
+
+ /* 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, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceAddress, numSpareAreaRead = 0, nandAddress, columnAddress, 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)0x00U);
+ __DSB();
+ }
+
+ /* Get Data into Buffer */
+ for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
+ {
+ *buff = *(uint8_t *)deviceAddress;
+ buff++;
+ }
+
+ /* Increment read spare areas number */
+ numSpareAreaRead++;
+
+ /* 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, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumSpareAreaToRead)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceAddress, numSpareAreaRead = 0, nandAddress, columnAddress, 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) * 2U);
+
+ /* 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)0x00U);
+ __DSB();
+ }
+
+ /* Get Data into Buffer */
+ for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
+ {
+ *buff = *(uint16_t *)deviceAddress;
+ buff++;
+ }
+
+ /* Increment read spare areas number */
+ numSpareAreaRead++;
+
+ /* 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, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceAddress, numSpareAreaWritten = 0, nandAddress, columnAddress, nbspare = NumSpareAreaTowrite;
+ 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;
+ }
+ }
+
+ /* Increment written spare areas number */
+ numSpareAreaWritten++;
+
+ /* 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, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumSpareAreaTowrite)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceAddress, numSpareAreaWritten = 0, nandAddress, columnAddress, nbspare = NumSpareAreaTowrite;
+ 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) * 2U);
+
+ /* 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;
+ }
+ }
+
+ /* Increment written spare areas number */
+ numSpareAreaWritten++;
+
+ /* 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, 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(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 instead of the weak (surcharged) 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;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hnand);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hnand);
+ return status;
+}
+
+/**
+ * @brief Unregister a User NAND Callback
+ * NAND Callback is redirected to the weak (surcharged) 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;
+
+ /* Process locked */
+ __HAL_LOCK(hnand);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hnand);
+ return status;
+}
+#endif
+
+/**
+ * @}
+ */
+
+/** @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(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(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 */
+
+/**
+ * @}
+ */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_nor.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_nor.c
new file mode 100644
index 0000000000..b58b8cfd79
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_nor.c
@@ -0,0 +1,1285 @@
+/**
+ ******************************************************************************
+ * @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.
+ *
+ @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 @ref 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 @ref HAL_NOR_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) 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 @ref HAL_NOR_Init and if the state is HAL_NOR_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_NOR_Init
+ and @ref HAL_NOR_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_NOR_Init and @ref 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 @ref HAL_NOR_RegisterCallback before calling @ref HAL_NOR_DeInit
+ or @ref 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 (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 (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
+
+/* Mask on NOR STATUS REGISTER */
+#define NOR_MASK_STATUS_DQ5 (uint16_t)0x0020
+#define NOR_MASK_STATUS_DQ6 (uint16_t)0x0040
+
+/**
+ * @}
+ */
+
+/* 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)
+{
+ /* 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;
+
+ return HAL_OK;
+}
+
+/**
+ * @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;
+
+ /* Check the NOR controller state */
+ state = hnor->State;
+ if (state == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_PROTECTED))
+ {
+ /* 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 */
+ 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);
+
+ /* 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 HAL_OK;
+}
+
+/**
+ * @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;
+
+ /* Check the NOR controller state */
+ state = hnor->State;
+ if (state == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_PROTECTED))
+ {
+ /* 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;
+ }
+
+ NOR_WRITE(deviceaddress, NOR_CMD_DATA_READ_RESET);
+
+ /* Check the NOR controller state */
+ hnor->State = state;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @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;
+
+ /* Check the NOR controller state */
+ state = hnor->State;
+ if (state == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_PROTECTED))
+ {
+ /* 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 */
+ 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);
+
+ /* 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 HAL_OK;
+}
+
+/**
+ * @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;
+
+ /* 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 */
+ 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);
+
+ /* 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 HAL_OK;
+}
+
+/**
+ * @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, size = uwBufferSize, address = uwAddress;
+ uint16_t *data = pData;
+ 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_READY) || (state == HAL_NOR_STATE_PROTECTED))
+ {
+ /* 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 */
+ 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);
+
+ /* 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 HAL_OK;
+}
+
+/**
+ * @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 lastloadedaddress, deviceaddress;
+
+ /* 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 *)(uwAddress);
+ p_endaddress = (const uint16_t *)(uwAddress + (uwBufferSize - 1U));
+ lastloadedaddress = uwAddress;
+
+ /* 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(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, uwAddress), NOR_CMD_DATA_BUFFER_AND_PROG);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, uwAddress), (uint16_t)(uwBufferSize - 1U));
+
+ /* Load Data into NOR Buffer */
+ while (p_currentaddress <= p_endaddress)
+ {
+ /* Store last loaded address & data value (for polling) */
+ lastloadedaddress = (uint32_t)p_currentaddress;
+
+ NOR_WRITE(p_currentaddress, *data);
+
+ data++;
+ p_currentaddress ++;
+ }
+
+ NOR_WRITE((uint32_t)(lastloadedaddress), NOR_CMD_DATA_BUFFER_AND_PROG_CONFIRM);
+
+ /* Check the NOR controller state */
+ hnor->State = HAL_NOR_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+
+}
+
+/**
+ * @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;
+
+ /* 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 */
+ 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);
+
+ /* 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 HAL_OK;
+
+}
+
+/**
+ * @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;
+ 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 */
+ 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);
+
+ /* 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 HAL_OK;
+}
+
+/**
+ * @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_READY) || (state == HAL_NOR_STATE_PROTECTED))
+ {
+ /* 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 */
+ 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 instead of the weak (surcharged) 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;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hnor);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hnor);
+ return status;
+}
+
+/**
+ * @brief Unregister a User NOR Callback
+ * NOR Callback is redirected to the weak (surcharged) 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;
+
+ /* Process locked */
+ __HAL_LOCK(hnor);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hnor);
+ 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(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, 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();
+ 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;
+ }
+ }
+
+ /* Return the operation status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_NOR_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_opamp.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_opamp.c
new file mode 100644
index 0000000000..21f75b010a
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_opamp.c
@@ -0,0 +1,1163 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_opamp.c
+ * @author MCD Application Team
+ * @brief OPAMP HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the operational amplifier(s) peripheral:
+ * + OPAMP configuration
+ * + OPAMP calibration
+ * Thanks to
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+================================================================================
+ ##### OPAMP Peripheral Features #####
+================================================================================
+
+ [..] The device integrates 2 operational amplifiers OPAMP1 & OPAMP2
+
+ (#) The OPAMP(s) provides several exclusive running modes.
+ (++) Standalone mode
+ (++) Programmable Gain Amplifier (PGA) modes
+ (++) Follower mode
+
+ (#) Each OPAMP(s) can be configured in normal and high speed mode.
+
+ (#) The OPAMP(s) provide(s) calibration capabilities.
+ (++) Calibration aims at correcting some offset for running mode.
+ (++) The OPAMP uses either factory calibration settings OR user defined
+ calibration (trimming) settings (i.e. trimming mode).
+ (++) The user defined settings can be figured out using self calibration
+ handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
+ (++) HAL_OPAMP_SelfCalibrate:
+ (+++) Runs automatically the calibration in 2 steps.
+ (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors).
+ (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is
+ appropriate and enough in most cases).
+ (+++) Runs automatically the calibration.
+ (+++) Enables the user trimming mode
+ (+++) Updates the init structure with trimming values with fresh calibration
+ results.
+ The user may store the calibration results for larger
+ (ex monitoring the trimming as a function of temperature
+ for instance)
+ (+++) HAL_OPAMPEx_SelfCalibrateAll
+ runs calibration of all OPAMPs in parallel to save search time.
+
+ (#) Running mode: Standalone mode
+ (++) Gain is set externally (gain depends on external loads).
+ (++) Follower mode also possible externally by connecting the inverting input to
+ the output.
+
+ (#) Running mode: Follower mode
+ (++) No Inverting Input is connected.
+
+ (#) Running mode: Programmable Gain Amplifier (PGA) mode
+ (Resistor feedback output)
+ (#) The OPAMP(s) output(s) can be internally connected to resistor feedback
+ output.
+ (#) OPAMP gain can be selected as :
+
+ (##) Gain of x2, x4, x8 or x16 for non inverting mode with:
+ (+++) VREF- referenced.
+ (+++) Filtering on VINM0, VREF- referenced.
+ (+++) VINM0 node for bias voltage and VINP0 for input signal.
+ (+++) VINM0 node for bias voltage and VINP0 for input signal, VINM1 node for filtering.
+
+ (##) Gain of x-1, x-3, x-7 or x-15 for inverting mode with:
+ (+++) VINM0 node for input signal and VINP0 for bias.
+ (+++) VINM0 node for input signal and VINP0 for bias voltage, VINM1 node for filtering.
+
+ (#) The OPAMPs inverting input can be selected according to the Reference Manual
+ "OPAMP functional description" chapter.
+
+ (#) The OPAMPs non inverting input can be selected according to the Reference Manual
+ "OPAMP functional description" chapter.
+
+
+ ##### How to use this driver #####
+================================================================================
+ [..]
+
+ *** High speed / normal power mode ***
+ ============================================
+ [..] To run in high speed mode:
+
+ (#) Configure the OPAMP using HAL_OPAMP_Init() function:
+ (++) Select OPAMP_POWERMODE_HIGHSPEED
+ (++) Otherwise select OPAMP_POWERMODE_NORMAL
+
+ *** Calibration ***
+ ============================================
+ [..] To run the OPAMP calibration self calibration:
+
+ (#) Start calibration using HAL_OPAMP_SelfCalibrate.
+ Store the calibration results.
+
+ *** Running mode ***
+ ============================================
+
+ [..] To use the OPAMP, perform the following steps:
+
+ (#) Fill in the HAL_OPAMP_MspInit() to
+ (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE()
+ (++) Configure the OPAMP input AND output in analog mode using
+ HAL_GPIO_Init() to map the OPAMP output to the GPIO pin.
+
+ (#) Registrate Callbacks
+ (++) The compilation define USE_HAL_OPAMP_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ (++) Use Functions @ref HAL_OPAMP_RegisterCallback() to register a user callback,
+ it allows to register following callbacks:
+ (+++) MspInitCallback : OPAMP MspInit.
+ (+++) MspDeInitCallback : OPAMP MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ (++) Use function @ref HAL_OPAMP_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function. It allows to reset following callbacks:
+ (+++) MspInitCallback : OPAMP MspInit.
+ (+++) MspDeInitCallback : OPAMP MspDeInit.
+ (+++) All Callbacks
+ (#) Configure the OPAMP using HAL_OPAMP_Init() function:
+ (++) Select the mode
+ (++) Select the inverting input
+ (++) Select the non-inverting input
+ (++) If PGA mode is enabled, Select if inverting input is connected.
+ (++) Select either factory or user defined trimming mode.
+ (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values
+ (typically values set by HAL_OPAMP_SelfCalibrate function).
+
+ (#) Enable the OPAMP using HAL_OPAMP_Start() function.
+
+ (#) Disable the OPAMP using HAL_OPAMP_Stop() function.
+
+ (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function.
+ Caution: On STM32H7, HAL OPAMP lock is software lock only (not
+ hardware lock as on some other STM32 devices)
+
+ (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function.
+
+ *** Running mode: change of configuration while OPAMP ON ***
+ ============================================
+ [..] To Re-configure OPAMP when OPAMP is ON (change on the fly)
+ (#) If needed, fill in the HAL_OPAMP_MspInit()
+ (++) This is the case for instance if you wish to use new OPAMP I/O
+
+ (#) Configure the OPAMP using HAL_OPAMP_Init() function:
+ (++) As in configure case, select first the parameters you wish to modify.
+
+ (#) Change from high speed mode to normal power mode (& vice versa) requires
+ first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init().
+ In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode
+ alone.
+
+ @endverbatim
+ ******************************************************************************
+ Table 1. OPAMPs inverting/non-inverting inputs for the STM32H7 devices:
+
+ +------------------------------------------------------------------------|
+ | | | OPAMP1 | OPAMP2 |
+ |-----------------|---------|----------------------|---------------------|
+ | Inverting Input | VM_SEL | VINM0-> PC5 | VINM0-> PE8 |
+ | | | VINM1-> PA7 | VINM1-> PG1 |
+ | | | Internal: | Internal: |
+ | | | ADC1_IN9 | OPAMP2_OUT |
+ | | | ADC2_IN9 | PGA mode |
+ | | | OPAMP1_OUT | |
+ | | | PGA mode | |
+ |-----------------|---------|----------------------|---------------------|
+ | Non Inverting | VP_SEL | | |
+ | | | VP0 -> PB0 (GPIO) | VP0 -> PE9 (GPIO) |
+ | | | Internal: | Internal: |
+ | Input | | DAC1_CH1_int | DAC1_CH2_int |
+ | | | ADC1_IN8 | DAC2_CH1_int |
+ | | | ADC2_IN8 | COMP2_INP |
+ | | | COMP1_INP | |
+ +------------------------------------------------------------------------|
+
+
+ [..] Table 2. OPAMPs outputs for the STM32H7 devices:
+
+ +-------------------------------------------------------------------------
+ | | | OPAMP1 | OPAMP2 |
+ |-----------------|--------|-----------------------|---------------------|
+ | Output | VOUT | PC4 | PE7 |
+ | | | & ADC1_IN4| | & COMP2_INN7 if |
+ | | | ADC2_IN4 |connected internally |
+ | | | COMP1_INN7 if | |
+ | | | connected internally | |
+ |-----------------|--------|-----------------------|---------------------|
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup OPAMP OPAMP
+ * @brief OPAMP module driver
+ * @{
+ */
+
+#ifdef HAL_OPAMP_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup OPAMP_Private_Constants
+ * @{
+ */
+
+/* CSR register reset value */
+#define OPAMP_CSR_RESET_VALUE 0x00000000U
+
+/* CSR Init masks */
+
+#define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_PGGAIN | OPAMP_CSR_PGGAIN \
+ | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM)
+
+
+#define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL| OPAMP_CSR_VPSEL \
+ | OPAMP_CSR_USERTRIM)
+
+
+#define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \
+ | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM)
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
+ * @{
+ */
+
+/** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the OPAMP according to the specified
+ * parameters in the OPAMP_InitTypeDef and initialize the associated handle.
+ * @note If the selected opamp is locked, initialization can't be performed.
+ * To unlock the configuration, perform a system reset.
+ * @param hopamp OPAMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t updateotrlpotr;
+
+ /* Check the OPAMP handle allocation and lock status */
+ /* Init not allowed if calibration is ongoing */
+ if(hopamp == NULL)
+ {
+ return HAL_ERROR;
+ }
+ else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
+ {
+ return HAL_ERROR;
+ }
+ else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
+
+ /* Set OPAMP parameters */
+ assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
+ assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
+ assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));
+
+#if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
+ if(hopamp->State == HAL_OPAMP_STATE_RESET)
+ {
+ if(hopamp->MspInitCallback == NULL)
+ {
+ hopamp->MspInitCallback = HAL_OPAMP_MspInit;
+ }
+ }
+#endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
+ if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
+ {
+ assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp->Init.InvertingInput));
+ }
+
+ if ((hopamp->Init.Mode) == OPAMP_PGA_MODE)
+ {
+ assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain));
+ assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect));
+ }
+
+
+ assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
+
+ if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER)
+ {
+ if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
+ {
+ assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
+ assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
+ }
+ else
+ {
+ assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePHighSpeed));
+ assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNHighSpeed));
+ }
+ }
+
+ if(hopamp->State == HAL_OPAMP_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hopamp->Lock = HAL_UNLOCKED;
+ }
+
+#if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
+ hopamp->MspInitCallback(hopamp);
+#else
+ /* Call MSP init function */
+ HAL_OPAMP_MspInit(hopamp);
+#endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
+
+ /* Set operating mode */
+ CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON);
+ /* In PGA mode InvertingInput is Not Applicable */
+ if (hopamp->Init.Mode == OPAMP_PGA_MODE)
+ {
+ MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_PGA, \
+ hopamp->Init.PowerMode | \
+ hopamp->Init.Mode | \
+ hopamp->Init.PgaGain | \
+ hopamp->Init.PgaConnect | \
+ hopamp->Init.NonInvertingInput | \
+ hopamp->Init.UserTrimming);
+ }
+
+ if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)
+ {
+ /* In Follower mode InvertingInput is Not Applicable */
+ MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_FOLLOWER, \
+ hopamp->Init.PowerMode | \
+ hopamp->Init.Mode | \
+ hopamp->Init.NonInvertingInput | \
+ hopamp->Init.UserTrimming);
+ }
+
+ if (hopamp->Init.Mode == OPAMP_STANDALONE_MODE)
+ {
+ MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_STANDALONE, \
+ hopamp->Init.PowerMode | \
+ hopamp->Init.Mode | \
+ hopamp->Init.InvertingInput | \
+ hopamp->Init.NonInvertingInput | \
+ hopamp->Init.UserTrimming);
+ }
+
+ if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
+ {
+ /* Set power mode and associated calibration parameters */
+ if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
+ {
+ /* OPAMP_POWERMODE_NORMAL */
+ /* Set calibration mode (factory or user) and values for */
+ /* transistors differential pair high (PMOS) and low (NMOS) for */
+ /* normal mode. */
+ updateotrlpotr = (((hopamp->Init.TrimmingValueP) << (OPAMP_INPUT_NONINVERTING)) \
+ | (hopamp->Init.TrimmingValueN));
+ MODIFY_REG(hopamp->Instance->OTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
+ }
+ else
+ {
+ /* OPAMP_POWERMODE_HIGHSPEED*/
+ /* transistors differential pair high (PMOS) and low (NMOS) for */
+ /* high speed mode. */
+ updateotrlpotr = (((hopamp->Init.TrimmingValuePHighSpeed) << (OPAMP_INPUT_NONINVERTING)) \
+ | (hopamp->Init.TrimmingValueNHighSpeed));
+ MODIFY_REG(hopamp->Instance->HSOTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
+ }
+ }
+
+ /* Update the OPAMP state*/
+ if (hopamp->State == HAL_OPAMP_STATE_RESET)
+ {
+ /* From RESET state to READY State */
+ hopamp->State = HAL_OPAMP_STATE_READY;
+ }
+ /* else: remain in READY or BUSY state (no update) */
+ return status;
+ }
+}
+
+/**
+ * @brief DeInitialize the OPAMP peripheral
+ * @note Deinitialization can be performed if the OPAMP configuration is locked.
+ * (the lock is SW in H7)
+ * @param hopamp OPAMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the OPAMP handle allocation */
+ /* DeInit not allowed if calibration is on going */
+ if(hopamp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
+
+ /* Set OPAMP_CSR register to reset value */
+ WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE);
+
+ /* DeInit the low level hardware */
+#if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
+ if(hopamp->MspDeInitCallback == NULL)
+ {
+ hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ hopamp->MspDeInitCallback(hopamp);
+#else
+ HAL_OPAMP_MspDeInit(hopamp);
+#endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
+
+ /* Update the OPAMP state*/
+ hopamp->State = HAL_OPAMP_STATE_RESET;
+ /* Process unlocked */
+ __HAL_UNLOCK(hopamp);
+
+ }
+
+ return status;
+}
+
+
+/**
+ * @brief Initialize the OPAMP MSP.
+ * @param hopamp OPAMP handle
+ * @retval None
+ */
+__weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hopamp);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief DeInitialize OPAMP MSP.
+ * @param hopamp OPAMP handle
+ * @retval None
+ */
+__weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hopamp);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+
+/** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
+ * @brief IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the OPAMP
+ start, stop and calibration actions.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the OPAMP.
+ * @param hopamp OPAMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the OPAMP handle allocation */
+ /* Check if OPAMP locked */
+ if(hopamp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
+
+ if(hopamp->State == HAL_OPAMP_STATE_READY)
+ {
+ /* Enable the selected opamp */
+ SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
+
+ /* Update the OPAMP state*/
+ /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
+ hopamp->State = HAL_OPAMP_STATE_BUSY;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ }
+ return status;
+}
+
+/**
+ * @brief Stop the OPAMP.
+ * @param hopamp OPAMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the OPAMP handle allocation */
+ /* Check if OPAMP locked */
+ /* Check if OPAMP calibration ongoing */
+ if(hopamp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
+ {
+ status = HAL_ERROR;
+ }
+ else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
+
+ if(hopamp->State == HAL_OPAMP_STATE_BUSY)
+ {
+ /* Disable the selected opamp */
+ CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
+
+ /* Update the OPAMP state*/
+ /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
+ hopamp->State = HAL_OPAMP_STATE_READY;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Run the self calibration of one OPAMP.
+ * @note Calibration is performed in the mode specified in OPAMP init
+ * structure (mode normal or high-speed). To perform calibration for
+ * both modes, repeat this function twice after OPAMP init structure
+ * accordingly updated.
+ * @param hopamp handle
+ * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp)
+{
+
+ HAL_StatusTypeDef status = HAL_OK;
+
+ uint32_t trimmingvaluen;
+ uint32_t trimmingvaluep;
+ uint32_t delta;
+ uint32_t opampmode;
+
+ __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or HSOTR */
+
+ /* Check the OPAMP handle allocation */
+ /* Check if OPAMP locked */
+ if(hopamp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+
+ /* Check if OPAMP in calibration mode and calibration not yet enable */
+ if(hopamp->State == HAL_OPAMP_STATE_READY)
+ {
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
+ assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
+
+ opampmode = READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_VMSEL);
+
+ /* Use of standalone mode */
+ MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, OPAMP_STANDALONE_MODE);
+ /* user trimming values are used for offset calibration */
+ SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
+
+ /* Select trimming settings depending on power mode */
+ if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
+ {
+ tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
+
+ }
+ else
+ {
+ /* high speed Mode */
+ tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
+ }
+
+
+ /* Enable calibration */
+ SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
+
+ /* Force internal reference on VP */
+ SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
+
+ /* 1st calibration - N */
+ MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
+
+ /* Enable the selected opamp */
+ SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
+
+ /* Init trimming counter */
+ /* Medium value */
+ trimmingvaluen = 16U;
+ delta = 8U;
+
+ while (delta != 0U)
+ {
+ /* Set candidate trimming */
+ /* OPAMP_POWERMODE_NORMAL */
+ MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
+
+ /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
+ /* Offset trim time: during calibration, minimum time needed between */
+ /* two steps to have 1 mV accuracy */
+ HAL_Delay(OPAMP_TRIMMING_DELAY);
+
+ if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
+ {
+ /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
+ trimmingvaluen += delta;
+ }
+ else
+ {
+ /* OPAMP_CSR_CALOUT is LOW try lower trimming */
+ trimmingvaluen -= delta;
+ }
+ /* Divide range by 2 to continue dichotomy sweep */
+ delta >>= 1;
+ }
+
+ /* Still need to check if right calibration is current value or one step below */
+ /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
+
+ MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
+
+ /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
+ /* Offset trim time: during calibration, minimum time needed between */
+ /* two steps to have 1 mV accuracy */
+ HAL_Delay(OPAMP_TRIMMING_DELAY);
+
+ if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)) != 0U)
+ {
+ /* Trimming value is actually one value more */
+ trimmingvaluen++;
+ /* Set right trimming */
+ MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
+ }
+
+ /* 2nd calibration - P */
+ MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
+
+ /* Init trimming counter */
+ /* Medium value */
+ trimmingvaluep = 16U;
+ delta = 8U;
+
+ while (delta != 0U)
+ {
+ /* Set candidate trimming */
+ /* OPAMP_POWERMODE_NORMAL */
+ MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
+
+ /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
+ /* Offset trim time: during calibration, minimum time needed between */
+ /* two steps to have 1 mV accuracy */
+ HAL_Delay(OPAMP_TRIMMING_DELAY);
+
+ if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
+ {
+ /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
+ trimmingvaluep += delta;
+ }
+ else
+ {
+ /* OPAMP_CSR_CALOUT is LOW try lower trimming */
+ trimmingvaluep -= delta;
+ }
+
+ /* Divide range by 2 to continue dichotomy sweep */
+ delta >>= 1U;
+ }
+
+ /* Still need to check if right calibration is current value or one step below */
+ /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
+ /* Set candidate trimming */
+ MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
+
+ /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
+ /* Offset trim time: during calibration, minimum time needed between */
+ /* two steps to have 1 mV accuracy */
+ HAL_Delay(OPAMP_TRIMMING_DELAY);
+
+ if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
+ {
+ /* Trimming value is actually one value more */
+ trimmingvaluep++;
+ MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
+ }
+
+ /* Disable calibration & set normal mode (operating mode) */
+ CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
+
+ /* Disable the OPAMP */
+ CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
+
+ /* Set operating mode back */
+ CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
+
+ /* Self calibration is successful */
+ /* Store calibration(user trimming) results in init structure. */
+
+ /* Set user trimming mode */
+ hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
+
+ /* Affect calibration parameters depending on mode normal/high speed */
+ if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
+ {
+ /* Write calibration result N */
+ hopamp->Init.TrimmingValueN = trimmingvaluen;
+ /* Write calibration result P */
+ hopamp->Init.TrimmingValueP = trimmingvaluep;
+ }
+ else
+ {
+ /* Write calibration result N */
+ hopamp->Init.TrimmingValueNHighSpeed = trimmingvaluen;
+ /* Write calibration result P */
+ hopamp->Init.TrimmingValuePHighSpeed = trimmingvaluep;
+ }
+ /* Restore OPAMP mode after calibration */
+ MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, opampmode);
+ }
+
+ else
+ {
+ /* OPAMP can not be calibrated from this mode */
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the OPAMP data
+ transfers.
+
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Lock the selected OPAMP configuration.
+ * @note On STM32H7, HAL OPAMP lock is software lock only (in
+ * contrast of hardware lock available on some other STM32
+ * devices)
+ * @param hopamp OPAMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the OPAMP handle allocation */
+ /* Check if OPAMP locked */
+ /* OPAMP can be locked when enabled and running in normal mode */
+ /* It is meaningless otherwise */
+ if(hopamp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+
+ else if(hopamp->State != HAL_OPAMP_STATE_BUSY)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
+
+ /* OPAMP state changed to locked */
+ hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
+ }
+ return status;
+}
+
+/**
+ * @brief Return the OPAMP factory trimming value.
+ * @note On STM32H7 OPAMP, user can retrieve factory trimming if
+ * OPAMP has never been set to user trimming before.
+ * Therefore, this function must be called when OPAMP init
+ * parameter "UserTrimming" is set to trimming factory,
+ * and before OPAMP calibration (function
+ * "HAL_OPAMP_SelfCalibrate()").
+ * Otherwise, factory trimming value cannot be retrieved and
+ * error status is returned.
+ * @param hopamp OPAMP handle
+ * @param trimmingoffset Trimming offset (P or N)
+ * This parameter must be a value of @ref OPAMP_FactoryTrimming
+ * @note Calibration parameter retrieved is corresponding to the mode
+ * specified in OPAMP init structure (mode normal or high-speed).
+ * To retrieve calibration parameters for both modes, repeat this
+ * function after OPAMP init structure accordingly updated.
+ * @retval Trimming value (P or N): range: 0->31
+ * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
+ *
+ */
+HAL_OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
+{
+ HAL_OPAMP_TrimmingValueTypeDef trimmingvalue;
+ __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
+
+ /* Check the OPAMP handle allocation */
+ /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
+ if(hopamp == NULL)
+ {
+ return OPAMP_FACTORYTRIMMING_DUMMY;
+ }
+
+ if(hopamp->State == HAL_OPAMP_STATE_READY)
+ {
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
+ assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
+ assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
+
+ /* Check the trimming mode */
+ if (READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM)!= 0U)
+ {
+ /* This function must called when OPAMP init parameter "UserTrimming" */
+ /* is set to trimming factory, and before OPAMP calibration (function */
+ /* "HAL_OPAMP_SelfCalibrate()"). */
+ /* Otherwise, factory trimming value cannot be retrieved and error */
+ /* status is returned. */
+ trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
+ }
+ else
+ {
+ /* Select trimming settings depending on power mode */
+ if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
+ {
+ tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
+ }
+ else
+ {
+ tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
+ }
+
+ /* Get factory trimming */
+ if (trimmingoffset == OPAMP_FACTORYTRIMMING_P)
+ {
+ /* OPAMP_FACTORYTRIMMING_P */
+ trimmingvalue = ((*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING;
+ }
+ else
+ {
+ /* OPAMP_FACTORYTRIMMING_N */
+ trimmingvalue = (*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETN;
+ }
+ }
+ }
+ else
+ {
+ return OPAMP_FACTORYTRIMMING_DUMMY;
+ }
+
+ return trimmingvalue;
+}
+
+/**
+ * @}
+ */
+
+
+/** @defgroup OPAMP_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.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the OPAMP handle state.
+ * @param hopamp OPAMP handle
+ * @retval HAL state
+ */
+HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp)
+{
+ /* Check the OPAMP handle allocation */
+ if(hopamp == NULL)
+ {
+ return HAL_OPAMP_STATE_RESET;
+ }
+
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
+
+ /* Return OPAMP handle state */
+ return hopamp->State;
+}
+
+/**
+ * @}
+ */
+
+#if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User OPAMP Callback
+ * To be used instead of the weak (surcharged) predefined callback
+ * @param hopamp OPAMP handle
+ * @param CallbackId ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MspInit callback ID
+ * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_OPAMP_RegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId, pOPAMP_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hopamp);
+
+ if(hopamp->State == HAL_OPAMP_STATE_READY)
+ {
+ switch (CallbackId)
+ {
+ case HAL_OPAMP_MSPINIT_CB_ID :
+ hopamp->MspInitCallback = pCallback;
+ break;
+ case HAL_OPAMP_MSPDEINIT_CB_ID :
+ hopamp->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hopamp->State == HAL_OPAMP_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_OPAMP_MSPINIT_CB_ID :
+ hopamp->MspInitCallback = pCallback;
+ break;
+ case HAL_OPAMP_MSPDEINIT_CB_ID :
+ hopamp->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hopamp);
+ return status;
+}
+
+/**
+ * @brief Unregister a User OPAMP Callback
+ * OPAMP Callback is redirected to the weak (surcharged) predefined callback
+ * @param hopamp OPAMP handle
+ * @param CallbackId ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MSP Init Callback ID
+ * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MSP DeInit Callback ID
+ * @arg @ref HAL_OPAMP_ALL_CB_ID OPAMP All Callbacks
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_OPAMP_UnRegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hopamp);
+
+ if(hopamp->State == HAL_OPAMP_STATE_READY)
+ {
+ switch (CallbackId)
+ {
+ case HAL_OPAMP_MSPINIT_CB_ID :
+ hopamp->MspInitCallback = HAL_OPAMP_MspInit;
+ break;
+ case HAL_OPAMP_MSPDEINIT_CB_ID :
+ hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
+ break;
+ case HAL_OPAMP_ALL_CB_ID :
+ hopamp->MspInitCallback = HAL_OPAMP_MspInit;
+ hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hopamp->State == HAL_OPAMP_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_OPAMP_MSPINIT_CB_ID :
+ hopamp->MspInitCallback = HAL_OPAMP_MspInit;
+ break;
+ case HAL_OPAMP_MSPDEINIT_CB_ID :
+ hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hopamp);
+ return status;
+}
+
+#endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
+ /**
+ * @}
+ */
+
+/**
+ * @}
+ */
+#endif /* HAL_OPAMP_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_opamp_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_opamp_ex.c
new file mode 100644
index 0000000000..3ad48a5f64
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_opamp_ex.c
@@ -0,0 +1,435 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_opamp_ex.c
+ * @author MCD Application Team
+ * @brief Extended OPAMP HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the operational amplifier(s)(OPAMP1, OPAMP2 etc)
+ * peripheral:
+ * + Extended Initialization and de-initialization functions
+ * + Extended Peripheral Control functions
+ *
+ @verbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup OPAMPEx OPAMPEx
+ * @brief OPAMP Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_OPAMP_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup OPAMPEx_Exported_Functions OPAMP Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup OPAMPEx_Exported_Functions_Group1 Extended Input and Output operation functions
+ * @brief Extended operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended IO operation functions #####
+ ===============================================================================
+ [..]
+ (+) OPAMP Self calibration.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Run the self calibration of 2 OPAMPs in parallel.
+ * @note Trimming values (PMOS & NMOS) are updated and user trimming is
+ * enabled is calibration is successful.
+ * @note Calibration is performed in the mode specified in OPAMP init
+ * structure (mode normal or low power). To perform calibration for
+ * both modes, repeat this function twice after OPAMP init structure
+ * accordingly updated.
+ * @param hopamp1 handle
+ * @param hopamp2 handle
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef *hopamp1, OPAMP_HandleTypeDef *hopamp2)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ uint32_t trimmingvaluen1;
+ uint32_t trimmingvaluep1;
+ uint32_t trimmingvaluen2;
+ uint32_t trimmingvaluep2;
+
+/* Selection of register of trimming depending on power mode: OTR or HSOTR */
+ __IO uint32_t* tmp_opamp1_reg_trimming;
+ __IO uint32_t* tmp_opamp2_reg_trimming;
+
+ uint32_t delta;
+ uint32_t opampmode1;
+ uint32_t opampmode2;
+
+ if((hopamp1 == NULL) || (hopamp2 == NULL))
+ {
+ status = HAL_ERROR;
+ }
+ /* Check if OPAMP in calibration mode and calibration not yet enable */
+ else if(hopamp1->State != HAL_OPAMP_STATE_READY)
+ {
+ status = HAL_ERROR;
+ }
+ else if(hopamp2->State != HAL_OPAMP_STATE_READY)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1->Instance));
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2->Instance));
+
+ assert_param(IS_OPAMP_POWERMODE(hopamp1->Init.PowerMode));
+ assert_param(IS_OPAMP_POWERMODE(hopamp2->Init.PowerMode));
+
+ /* Set Calibration mode */
+ /* Non-inverting input connected to calibration reference voltage. */
+ SET_BIT(hopamp1->Instance->CSR, OPAMP_CSR_FORCEVP);
+ SET_BIT(hopamp2->Instance->CSR, OPAMP_CSR_FORCEVP);
+
+ /* Save OPAMP mode */
+ opampmode1 = READ_BIT(hopamp1->Instance->CSR,OPAMP_CSR_VMSEL);
+ opampmode2 = READ_BIT(hopamp2->Instance->CSR,OPAMP_CSR_VMSEL);
+
+ /* Use of standalone mode */
+ MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_VMSEL, OPAMP_STANDALONE_MODE);
+ MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_VMSEL, OPAMP_STANDALONE_MODE);
+
+ /* user trimming values are used for offset calibration */
+ SET_BIT(hopamp1->Instance->CSR, OPAMP_CSR_USERTRIM);
+ SET_BIT(hopamp2->Instance->CSR, OPAMP_CSR_USERTRIM);
+
+ /* Select trimming settings depending on power mode */
+ if (hopamp1->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
+ {
+ tmp_opamp1_reg_trimming = &OPAMP1->OTR;
+ }
+ else
+ {
+ tmp_opamp1_reg_trimming = &OPAMP1->HSOTR;
+ }
+
+ if (hopamp2->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
+ {
+ tmp_opamp2_reg_trimming = &OPAMP2->OTR;
+ }
+ else
+ {
+ tmp_opamp2_reg_trimming = &OPAMP2->HSOTR;
+ }
+
+ /* Enable calibration */
+ SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
+ SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
+
+ /* 1st calibration - N */
+ /* Select 90U% VREF */
+ MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
+ MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
+
+ /* Enable the selected opamp */
+ SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
+ SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
+
+ /* Init trimming counter */
+ /* Medium value */
+ trimmingvaluen1 = 16U;
+ trimmingvaluen2 = 16U;
+ delta = 8U;
+
+ while (delta != 0U)
+ {
+ /* Set candidate trimming */
+ /* OPAMP_POWERMODE_NORMAL */
+ MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1);
+ MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2);
+
+ /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
+ /* Offset trim time: during calibration, minimum time needed between */
+ /* two steps to have 1 mV accuracy */
+ HAL_Delay(OPAMP_TRIMMING_DELAY);
+
+ if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
+ {
+ /* OPAMP_CSR_CALOUT is Low try higher trimming */
+ trimmingvaluen1 += delta;
+ }
+ else
+ {
+ /* OPAMP_CSR_CALOUT is High try lower trimming */
+ trimmingvaluen1 -= delta;
+ }
+
+ if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
+ {
+ /* OPAMP_CSR_CALOUT is Low try higher trimming */
+ trimmingvaluen2 += delta;
+ }
+ else
+ {
+ /* OPAMP_CSR_CALOUT is High try lower trimming */
+ trimmingvaluen2 -= delta;
+ }
+ /* Divide range by 2 to continue dichotomy sweep */
+ delta >>= 1U;
+ }
+
+ /* Still need to check if right calibration is current value or one step below */
+ /* Indeed the first value that causes the OUTCAL bit to change from 0 to 1 */
+ /* Set candidate trimming */
+ MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1);
+ MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2);
+
+ /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
+ /* Offset trim time: during calibration, minimum time needed between */
+ /* two steps to have 1 mV accuracy */
+ HAL_Delay(OPAMP_TRIMMING_DELAY);
+
+ if ((READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT)) != 0U)
+ {
+ /* Trimming value is actually one value more */
+ trimmingvaluen1++;
+ MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen1);
+ }
+
+ if ((READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT)) != 0U)
+ {
+ /* Trimming value is actually one value more */
+ trimmingvaluen2++;
+ MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen2);
+ }
+
+ /* 2nd calibration - P */
+ /* Select 10U% VREF */
+ MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
+ MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
+
+ /* Init trimming counter */
+ /* Medium value */
+ trimmingvaluep1 = 16U;
+ trimmingvaluep2 = 16U;
+ delta = 8U;
+
+ while (delta != 0U)
+ {
+ /* Set candidate trimming */
+ /* OPAMP_POWERMODE_NORMAL */
+ MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING));
+ MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING));
+
+ /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
+ /* Offset trim time: during calibration, minimum time needed between */
+ /* two steps to have 1 mV accuracy */
+ HAL_Delay(OPAMP_TRIMMING_DELAY);
+
+ if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
+ {
+ /* OPAMP_CSR_CALOUT is Low try higher trimming */
+ trimmingvaluep1 += delta;
+ }
+ else
+ {
+ /* OPAMP_CSR_CALOUT is HIGH try lower trimming */
+ trimmingvaluep1 -= delta;
+ }
+
+ if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
+ {
+ /* OPAMP_CSR_CALOUT is Low try higher trimming */
+ trimmingvaluep2 += delta;
+ }
+ else
+ {
+ /* OPAMP_CSR_CALOUT is High try lower trimming */
+ trimmingvaluep2 -= delta;
+ }
+ /* Divide range by 2 to continue dichotomy sweep */
+ delta >>= 1U;
+ }
+
+ /* Still need to check if right calibration is current value or one step below */
+ /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
+ /* Set candidate trimming */
+ MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING));
+ MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING));
+
+ /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
+ /* Offset trim time: during calibration, minimum time needed between */
+ /* two steps to have 1 mV accuracy */
+ HAL_Delay(OPAMP_TRIMMING_DELAY);
+
+ if (READ_BIT(hopamp1->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
+ {
+ /* Trimming value is actually one value more */
+ trimmingvaluep1++;
+ MODIFY_REG(*tmp_opamp1_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep1<<OPAMP_INPUT_NONINVERTING));
+ }
+
+ if (READ_BIT(hopamp2->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
+ {
+ /* Trimming value is actually one value more */
+ trimmingvaluep2++;
+ MODIFY_REG(*tmp_opamp2_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep2<<OPAMP_INPUT_NONINVERTING));
+ }
+
+ /* Disable calibration & set normal mode (operating mode) */
+ CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
+ CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
+
+ /* Disable the OPAMPs */
+ CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
+ CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
+
+ /* Self calibration is successful */
+ /* Store calibration (user trimming) results in init structure. */
+
+ /* Set user trimming mode */
+ hopamp1->Init.UserTrimming = OPAMP_TRIMMING_USER;
+ hopamp2->Init.UserTrimming = OPAMP_TRIMMING_USER;
+
+ /* Affect calibration parameters depending on mode normal/high speed */
+ if (hopamp1->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
+ {
+ /* Write calibration result N */
+ hopamp1->Init.TrimmingValueN = trimmingvaluen1;
+ /* Write calibration result P */
+ hopamp1->Init.TrimmingValueP = trimmingvaluep1;
+ }
+ else
+ {
+ /* Write calibration result N */
+ hopamp1->Init.TrimmingValueNHighSpeed = trimmingvaluen1;
+ /* Write calibration result P */
+ hopamp1->Init.TrimmingValuePHighSpeed = trimmingvaluep1;
+ }
+
+ if (hopamp2->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
+ {
+ /* Write calibration result N */
+ hopamp2->Init.TrimmingValueN = trimmingvaluen2;
+ /* Write calibration result P */
+ hopamp2->Init.TrimmingValueP = trimmingvaluep2;
+ }
+ else
+ {
+ /* Write calibration result N */
+ hopamp2->Init.TrimmingValueNHighSpeed = trimmingvaluen2;
+ /* Write calibration result P */
+ hopamp2->Init.TrimmingValuePHighSpeed = trimmingvaluep2;
+
+ }
+ /* Update OPAMP state */
+ hopamp1->State = HAL_OPAMP_STATE_READY;
+ hopamp2->State = HAL_OPAMP_STATE_READY;
+
+ /* Restore OPAMP mode after calibration */
+ MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_VMSEL, opampmode1);
+ MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_VMSEL, opampmode2);
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup OPAMPEx_Exported_Functions_Group2 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ (+) OPAMP unlock.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Unlock the selected OPAMP configuration.
+ * @note This function must be called only when OPAMP is in state "locked".
+ * @param hopamp: OPAMP handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OPAMPEx_Unlock(OPAMP_HandleTypeDef* hopamp)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the OPAMP handle allocation */
+ /* Check if OPAMP locked */
+ if(hopamp == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ /* Check the OPAMP handle allocation */
+ /* Check if OPAMP locked */
+ else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
+ {
+ /* Check the parameter */
+ assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
+
+ /* OPAMP state changed to locked */
+ hopamp->State = HAL_OPAMP_STATE_BUSY;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_OPAMP_MODULE_ENABLED */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_ospi.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_ospi.c
new file mode 100644
index 0000000000..6036974978
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_ospi.c
@@ -0,0 +1,3068 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_ospi.c
+ * @author MCD Application Team
+ * @brief OSPI HAL module driver.
+ This file provides firmware functions to manage the following
+ functionalities of the OctoSPI interface (OSPI).
+ + Initialization and de-initialization functions
+ + Hyperbus configuration
+ + Indirect functional mode management
+ + Memory-mapped functional mode management
+ + Auto-polling functional mode management
+ + Interrupts and flags management
+ + DMA channel configuration for indirect functional mode
+ + Errors management and abort functionality
+ + IO manager configuration
+
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ *** Initialization ***
+ ======================
+ [..]
+ (#) As prerequisite, fill in the HAL_OSPI_MspInit() :
+ (++) Enable OctoSPI and OctoSPIM clocks interface with __HAL_RCC_OSPIx_CLK_ENABLE().
+ (++) Reset OctoSPI Peripheral with __HAL_RCC_OSPIx_FORCE_RESET() and __HAL_RCC_OSPIx_RELEASE_RESET().
+ (++) Enable the clocks for the OctoSPI GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE().
+ (++) Configure these OctoSPI pins in alternate mode using HAL_GPIO_Init().
+ (++) If interrupt or DMA mode is used, enable and configure OctoSPI global
+ interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
+ (++) If DMA mode is used, enable the clocks for the OctoSPI DMA channel
+ with __HAL_RCC_DMAx_CLK_ENABLE(), configure DMA with HAL_DMA_Init(),
+ link it with OctoSPI handle using __HAL_LINKDMA(), enable and configure
+ DMA channel global interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
+ (#) Configure the fifo threshold, the dual-quad mode, the memory type, the
+ device size, the CS high time, the free running clock, the clock mode,
+ the wrap size, the clock prescaler, the sample shifting, the hold delay
+ and the CS boundary using the HAL_OSPI_Init() function.
+ (#) When using Hyperbus, configure the RW recovery time, the access time,
+ the write latency and the latency mode unsing the HAL_OSPI_HyperbusCfg()
+ function.
+
+ *** Indirect functional mode ***
+ ================================
+ [..]
+ (#) In regular mode, configure the command sequence using the HAL_OSPI_Command()
+ or HAL_OSPI_Command_IT() functions :
+ (++) Instruction phase : the mode used and if present the size, the instruction
+ opcode and the DTR mode.
+ (++) Address phase : the mode used and if present the size, the address
+ value and the DTR mode.
+ (++) Alternate-bytes phase : the mode used and if present the size, the
+ alternate bytes values and the DTR mode.
+ (++) 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 and the DTR mode.
+ (++) Data strobe (DQS) mode : the activation (or not) of this mode
+ (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode.
+ (++) Flash identifier : in dual-quad mode, indicates which flash is concerned
+ (++) Operation type : always common configuration
+ (#) In Hyperbus mode, configure the command sequence using the HAL_OSPI_HyperbusCmd()
+ function :
+ (++) Address space : indicate if the access will be done in register or memory
+ (++) Address size
+ (++) Number of data
+ (++) Data strobe (DQS) mode : the activation (or not) of this mode
+ (#) If no data is required for the command (only for regular mode, not for
+ Hyperbus mode), 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_OSPI_CmdCpltCallback() will be called when the transfer is complete.
+ (#) For the indirect write mode, use HAL_OSPI_Transmit(), HAL_OSPI_Transmit_DMA() or
+ HAL_OSPI_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_OSPI_FifoThresholdCallback() will be called when the fifo threshold
+ is reached and HAL_OSPI_TxCpltCallback() will be called when the transfer is complete.
+ (++) In DMA mode, HAL_OSPI_TxHalfCpltCallback() will be called at the half transfer and
+ HAL_OSPI_TxCpltCallback() will be called when the transfer is complete.
+ (#) For the indirect read mode, use HAL_OSPI_Receive(), HAL_OSPI_Receive_DMA() or
+ HAL_OSPI_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_OSPI_FifoThresholdCallback() will be called when the fifo threshold
+ is reached and HAL_OSPI_RxCpltCallback() will be called when the transfer is complete.
+ (++) In DMA mode, HAL_OSPI_RxHalfCpltCallback() will be called at the half transfer and
+ HAL_OSPI_RxCpltCallback() will be called when the transfer is complete.
+
+ *** Auto-polling functional mode ***
+ ====================================
+ [..]
+ (#) Configure the command sequence by the same way than the indirect mode
+ (#) Configure the auto-polling functional mode using the HAL_OSPI_AutoPolling()
+ or HAL_OSPI_AutoPolling_IT() functions :
+ (++) 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_OSPI_StatusMatchCallback() will be called each time the status match is reached.
+ *** MDMA functional mode ***
+ ====================================
+ [..]
+ (#) Configure the SourceInc and DestinationInc of MDMA paramters in the HAL_OSPI_MspInit() function :
+ (++) MDMA settings for write operation :
+ (+) The DestinationInc should be MDMA_DEST_INC_DISABLE
+ (+) The SourceInc must be a value of @ref MDMA_Source_increment_mode (Except the MDMA_SRC_INC_DOUBLEWORD).
+ (+) The SourceDataSize must be a value of @ref MDMA Source data size (Except the MDMA_SRC_DATASIZE_DOUBLEWORD)
+ aligned with @ref MDMA_Source_increment_mode .
+ (+) The DestDataSize must be a value of @ref 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 @ref MDMA_Destination_increment_mode (Except the MDMA_DEST_INC_DOUBLEWORD).
+ (+) The SourceDataSize must be a value of @ref MDMA Source data size (Except the MDMA_SRC_DATASIZE_DOUBLEWORD) .
+ (+) The DestDataSize must be a value of @ref MDMA Destination data size (Except the MDMA_DEST_DATASIZE_DOUBLEWORD)
+ aligned with @ref MDMA_Destination_increment_mode.
+ (++)The buffer Transfer Length (BufferTransferLength) = number of bytes in the FIFO (FifoThreshold) of the Octospi.
+ (#)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_OSPI_Transmit_DMA().
+ (++) For read operation :
+ (+) If the SourceInc is not set to MDMA_SRC_INC_DISABLE , it will be disabled by the HAL_OSPI_Receive_DMA().
+
+ *** Memory-mapped functional mode ***
+ =====================================
+ [..]
+ (#) Configure the command sequence by the same way than the indirect mode except
+ for the operation type in regular mode :
+ (++) Operation type equals to read configuration : the command configuration
+ applies to read access in memory-mapped mode
+ (++) Operation type equals to write configuration : the command configuration
+ applies to write access in memory-mapped mode
+ (++) Both read and write configuration should be performed before activating
+ memory-mapped mode
+ (#) Configure the memory-mapped functional mode using the HAL_OSPI_MemoryMapped()
+ functions :
+ (++) The timeout activation and the timeout period.
+ (#) After the configuration, the OctoSPI will be used as soon as an access on the AHB is done on
+ the address range. HAL_OSPI_TimeOutCallback() will be called when the timeout expires.
+
+ *** Errors management and abort functionality ***
+ =================================================
+ [..]
+ (#) HAL_OSPI_GetError() function gives the error raised during the last operation.
+ (#) HAL_OSPI_Abort() and HAL_OSPI_AbortIT() 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_OSPI_AbortCpltCallback() will be called when
+ the transfer complete bit is set.
+
+ *** Control functions ***
+ =========================
+ [..]
+ (#) HAL_OSPI_GetState() function gives the current state of the HAL OctoSPI driver.
+ (#) HAL_OSPI_SetTimeout() function configures the timeout value used in the driver.
+ (#) HAL_OSPI_SetFifoThreshold() function configures the threshold on the Fifo of the OSPI Peripheral.
+ (#) HAL_OSPI_GetFifoThreshold() function gives the current of the Fifo's threshold
+
+ *** IO manager configuration functions ***
+ ==========================================
+ [..]
+ (#) HAL_OSPIM_Config() function configures the IO manager for the OctoSPI instance.
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_OSPI_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ Use Functions @ref HAL_OSPI_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.
+ (+) RxHalfCpltCallback : callback when half of the reception transfer is completed.
+ (+) TxHalfCpltCallback : callback when half of the transmission transfer is completed.
+ (+) StatusMatchCallback : callback when a status match occurs.
+ (+) TimeOutCallback : callback when the timeout perioed expires.
+ (+) MspInitCallback : OSPI MspInit.
+ (+) MspDeInitCallback : OSPI MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function @ref HAL_OSPI_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) 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.
+ (+) RxHalfCpltCallback : callback when half of the reception transfer is completed.
+ (+) TxHalfCpltCallback : callback when half of the transmission transfer is completed.
+ (+) StatusMatchCallback : callback when a status match occurs.
+ (+) TimeOutCallback : callback when the timeout perioed expires.
+ (+) MspInitCallback : OSPI MspInit.
+ (+) MspDeInitCallback : OSPI MspDeInit.
+ This function) takes as parameters the HAL peripheral handle and the Callback ID.
+
+ By default, after the @ref HAL_OSPI_Init and if the state is HAL_OSPI_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_OSPI_Init
+ and @ref HAL_OSPI_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_OSPI_Init and @ref HAL_OSPI_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 @ref HAL_OSPI_RegisterCallback before calling @ref HAL_OSPI_DeInit
+ or @ref HAL_OSPI_Init function.
+
+ When The compilation define USE_HAL_OSPI_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2018 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+#if defined(OCTOSPI) || defined(OCTOSPI1) || defined(OCTOSPI2)
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup OSPI OSPI
+ * @brief OSPI HAL module driver
+ * @{
+ */
+
+#ifdef HAL_OSPI_MODULE_ENABLED
+
+/**
+ @cond 0
+ */
+/* Private typedef -----------------------------------------------------------*/
+
+/* Private define ------------------------------------------------------------*/
+#define OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE ((uint32_t)0x00000000) /*!< Indirect write mode */
+#define OSPI_FUNCTIONAL_MODE_INDIRECT_READ ((uint32_t)OCTOSPI_CR_FMODE_0) /*!< Indirect read mode */
+#define OSPI_FUNCTIONAL_MODE_AUTO_POLLING ((uint32_t)OCTOSPI_CR_FMODE_1) /*!< Automatic polling mode */
+#define OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED ((uint32_t)OCTOSPI_CR_FMODE) /*!< Memory-mapped mode */
+
+#define OSPI_CFG_STATE_MASK 0x00000004U
+#define OSPI_BUSY_STATE_MASK 0x00000008U
+
+#define OSPI_NB_INSTANCE 2U
+#define OSPI_IOM_NB_PORTS 2U
+#define OSPI_IOM_PORT_MASK 0x1U
+
+/* Private macro -------------------------------------------------------------*/
+#define IS_OSPI_FUNCTIONAL_MODE(MODE) (((MODE) == OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE) || \
+ ((MODE) == OSPI_FUNCTIONAL_MODE_INDIRECT_READ) || \
+ ((MODE) == OSPI_FUNCTIONAL_MODE_AUTO_POLLING) || \
+ ((MODE) == OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED))
+
+/* Private variables ---------------------------------------------------------*/
+
+/* Private function prototypes -----------------------------------------------*/
+static void OSPI_DMACplt (MDMA_HandleTypeDef *hmdma);
+static void OSPI_DMAError (MDMA_HandleTypeDef *hmdma);
+static void OSPI_DMAAbortCplt (MDMA_HandleTypeDef *hmdma);
+static HAL_StatusTypeDef OSPI_WaitFlagStateUntilTimeout(OSPI_HandleTypeDef *hospi, uint32_t Flag, FlagStatus State, uint32_t Tickstart, uint32_t Timeout);
+static HAL_StatusTypeDef OSPI_ConfigCmd (OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd);
+static HAL_StatusTypeDef OSPIM_GetConfig (uint8_t instance_nb, OSPIM_CfgTypeDef *cfg);
+/**
+ @endcond
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup OSPI_Exported_Functions OSPI Exported Functions
+ * @{
+ */
+
+/** @defgroup OSPI_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 OctoSPI.
+ (+) De-initialize the OctoSPI.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the OSPI mode according to the specified parameters
+ * in the OSPI_InitTypeDef and initialize the associated handle.
+ * @param hospi : OSPI handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_Init (OSPI_HandleTypeDef *hospi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the OSPI handle allocation */
+ if (hospi == NULL)
+ {
+ status = HAL_ERROR;
+ /* No error code can be set set as the handler is null */
+ }
+ else
+ {
+ /* Check the parameters of the initialization structure */
+ assert_param(IS_OSPI_FIFO_THRESHOLD (hospi->Init.FifoThreshold));
+ assert_param(IS_OSPI_DUALQUAD_MODE (hospi->Init.DualQuad));
+ assert_param(IS_OSPI_MEMORY_TYPE (hospi->Init.MemoryType));
+ assert_param(IS_OSPI_DEVICE_SIZE (hospi->Init.DeviceSize));
+ assert_param(IS_OSPI_CS_HIGH_TIME (hospi->Init.ChipSelectHighTime));
+ assert_param(IS_OSPI_FREE_RUN_CLK (hospi->Init.FreeRunningClock));
+ assert_param(IS_OSPI_CLOCK_MODE (hospi->Init.ClockMode));
+ assert_param(IS_OSPI_WRAP_SIZE (hospi->Init.WrapSize));
+ assert_param(IS_OSPI_CLK_PRESCALER (hospi->Init.ClockPrescaler));
+ assert_param(IS_OSPI_SAMPLE_SHIFTING(hospi->Init.SampleShifting));
+ assert_param(IS_OSPI_DHQC (hospi->Init.DelayHoldQuarterCycle));
+ assert_param(IS_OSPI_CS_BOUNDARY (hospi->Init.ChipSelectBoundary));
+ assert_param(IS_OSPI_CKCSHT (hospi->Init.ClkChipSelectHighTime));
+ assert_param(IS_OSPI_DLYBYP (hospi->Init.DelayBlockBypass));
+ assert_param(IS_OSPI_MAXTRAN (hospi->Init.MaxTran));
+
+ /* Initialize error code */
+ hospi->ErrorCode = HAL_OSPI_ERROR_NONE;
+
+ /* Check if the state is the reset state */
+ if (hospi->State == HAL_OSPI_STATE_RESET)
+ {
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ /* Reset Callback pointers in HAL_OSPI_STATE_RESET only */
+ hospi->ErrorCallback = HAL_OSPI_ErrorCallback;
+ hospi->AbortCpltCallback = HAL_OSPI_AbortCpltCallback;
+ hospi->FifoThresholdCallback = HAL_OSPI_FifoThresholdCallback;
+ hospi->CmdCpltCallback = HAL_OSPI_CmdCpltCallback;
+ hospi->RxCpltCallback = HAL_OSPI_RxCpltCallback;
+ hospi->TxCpltCallback = HAL_OSPI_TxCpltCallback;
+ hospi->RxHalfCpltCallback = HAL_OSPI_RxHalfCpltCallback;
+ hospi->TxHalfCpltCallback = HAL_OSPI_TxHalfCpltCallback;
+ hospi->StatusMatchCallback = HAL_OSPI_StatusMatchCallback;
+ hospi->TimeOutCallback = HAL_OSPI_TimeOutCallback;
+
+ if(hospi->MspInitCallback == NULL)
+ {
+ hospi->MspInitCallback = HAL_OSPI_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hospi->MspInitCallback(hospi);
+#else
+ /* Initialization of the low level hardware */
+ HAL_OSPI_MspInit(hospi);
+#endif
+
+ /* Configure the default timeout for the OSPI memory access */
+ (void)HAL_OSPI_SetTimeout(hospi, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
+
+ /* Configure memory type, device size, chip select high time, clocked chip select high time, delay block bypass, free running clock, clock mode */
+ MODIFY_REG(hospi->Instance->DCR1,
+ (OCTOSPI_DCR1_MTYP | OCTOSPI_DCR1_DEVSIZE | OCTOSPI_DCR1_CSHT | OCTOSPI_DCR1_CKCSHT |
+ OCTOSPI_DCR1_DLYBYP | OCTOSPI_DCR1_FRCK | OCTOSPI_DCR1_CKMODE),
+ (hospi->Init.MemoryType | ((hospi->Init.DeviceSize - 1U) << OCTOSPI_DCR1_DEVSIZE_Pos) |
+ ((hospi->Init.ChipSelectHighTime - 1U) << OCTOSPI_DCR1_CSHT_Pos) |
+ (hospi->Init.ClkChipSelectHighTime << OCTOSPI_DCR1_CKCSHT_Pos) |
+ hospi->Init.DelayBlockBypass | hospi->Init.ClockMode));
+
+ /* Configure wrap size */
+ MODIFY_REG(hospi->Instance->DCR2, OCTOSPI_DCR2_WRAPSIZE, hospi->Init.WrapSize);
+
+ /* Configure chip select boundary and maximun transfer */
+ hospi->Instance->DCR3 = ((hospi->Init.ChipSelectBoundary << OCTOSPI_DCR3_CSBOUND_Pos) | (hospi->Init.MaxTran << OCTOSPI_DCR3_MAXTRAN_Pos));
+
+ /* Configure refresh */
+ hospi->Instance->DCR4 = hospi->Init.Refresh;
+
+ /* Configure FIFO threshold */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FTHRES, ((hospi->Init.FifoThreshold - 1U) << OCTOSPI_CR_FTHRES_Pos));
+
+ /* Wait till busy flag is reset */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure clock prescaler */
+ MODIFY_REG(hospi->Instance->DCR2, OCTOSPI_DCR2_PRESCALER, ((hospi->Init.ClockPrescaler - 1U) << OCTOSPI_DCR2_PRESCALER_Pos));
+
+ /* Configure Dual Quad mode */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_DQM, hospi->Init.DualQuad);
+
+ /* Configure sample shifting and delay hold quarter cycle */
+ MODIFY_REG(hospi->Instance->TCR, (OCTOSPI_TCR_SSHIFT | OCTOSPI_TCR_DHQC), (hospi->Init.SampleShifting | hospi->Init.DelayHoldQuarterCycle));
+
+ /* Enable OctoSPI */
+ __HAL_OSPI_ENABLE(hospi);
+
+ /* Enable free running clock if needed : must be done after OSPI enable */
+ if (hospi->Init.FreeRunningClock == HAL_OSPI_FREERUNCLK_ENABLE)
+ {
+ SET_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK);
+ }
+
+ /* Initialize the OSPI state */
+ if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
+ {
+ hospi->State = HAL_OSPI_STATE_HYPERBUS_INIT;
+ }
+ else
+ {
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+ }
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Initialize the OSPI MSP.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_MspInit(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_OSPI_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief De-Initialize the OSPI peripheral.
+ * @param hospi : OSPI handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_DeInit(OSPI_HandleTypeDef *hospi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the OSPI handle allocation */
+ if (hospi == NULL)
+ {
+ status = HAL_ERROR;
+ /* No error code can be set set as the handler is null */
+ }
+ else
+ {
+ /* Disable OctoSPI */
+ __HAL_OSPI_DISABLE(hospi);
+
+ /* Disable free running clock if needed : must be done after OSPI disable */
+ CLEAR_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK);
+
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ if(hospi->MspDeInitCallback == NULL)
+ {
+ hospi->MspDeInitCallback = HAL_OSPI_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hospi->MspDeInitCallback(hospi);
+#else
+ /* De-initialize the low-level hardware */
+ HAL_OSPI_MspDeInit(hospi);
+#endif
+
+ /* Reset the driver state */
+ hospi->State = HAL_OSPI_STATE_RESET;
+ }
+
+ return status;
+}
+
+/**
+ * @brief DeInitialize the OSPI MSP.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_MspDeInit(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_OSPI_MspDeInit can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup OSPI_Exported_Functions_Group2 Input and Output operation functions
+ * @brief OSPI Transmit/Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to :
+ (+) Handle the interrupts.
+ (+) Handle the command sequence (regular and Hyperbus).
+ (+) Handle the Hyperbus configuration.
+ (+) 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 OSPI interrupt request.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+void HAL_OSPI_IRQHandler(OSPI_HandleTypeDef *hospi)
+{
+ __IO uint32_t *data_reg = &hospi->Instance->DR;
+ uint32_t flag = hospi->Instance->SR;
+ uint32_t itsource = hospi->Instance->CR;
+ uint32_t currentstate = hospi->State;
+
+ /* OctoSPI fifo threshold interrupt occurred -------------------------------*/
+ if (((flag & HAL_OSPI_FLAG_FT) != 0U) && ((itsource & HAL_OSPI_IT_FT) != 0U))
+ {
+ if (currentstate == HAL_OSPI_STATE_BUSY_TX)
+ {
+ /* Write a data in the fifo */
+ *((__IO uint8_t *)data_reg) = *hospi->pBuffPtr;
+ hospi->pBuffPtr++;
+ hospi->XferCount--;
+ }
+ else if (currentstate == HAL_OSPI_STATE_BUSY_RX)
+ {
+ /* Read a data from the fifo */
+ *hospi->pBuffPtr = *((__IO uint8_t *)data_reg);
+ hospi->pBuffPtr++;
+ hospi->XferCount--;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if (hospi->XferCount == 0U)
+ {
+ /* All data have been received or transmitted for the transfer */
+ /* Disable fifo threshold interrupt */
+ __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_FT);
+ }
+
+ /* Fifo threshold callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->FifoThresholdCallback(hospi);
+#else
+ HAL_OSPI_FifoThresholdCallback(hospi);
+#endif
+ }
+ /* OctoSPI transfer complete interrupt occurred ----------------------------*/
+ else if (((flag & HAL_OSPI_FLAG_TC) != 0U) && ((itsource & HAL_OSPI_IT_TC) != 0U))
+ {
+ if (currentstate == HAL_OSPI_STATE_BUSY_RX)
+ {
+ if ((hospi->XferCount > 0U) && ((flag & OCTOSPI_SR_FLEVEL) != 0U))
+ {
+ /* Read the last data received in the fifo */
+ *hospi->pBuffPtr = *((__IO uint8_t *)data_reg);
+ hospi->pBuffPtr++;
+ hospi->XferCount--;
+ }
+ else if(hospi->XferCount == 0U)
+ {
+ /* Clear flag */
+ hospi->Instance->FCR = HAL_OSPI_FLAG_TC;
+
+ /* Disable the interrupts */
+ __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
+
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+
+ /* RX complete callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->RxCpltCallback(hospi);
+#else
+ HAL_OSPI_RxCpltCallback(hospi);
+#endif
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ else
+ {
+ /* Clear flag */
+ hospi->Instance->FCR = HAL_OSPI_FLAG_TC;
+
+ /* Disable the interrupts */
+ __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
+
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+
+ if (currentstate == HAL_OSPI_STATE_BUSY_TX)
+ {
+ /* TX complete callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->TxCpltCallback(hospi);
+#else
+ HAL_OSPI_TxCpltCallback(hospi);
+#endif
+ }
+ else if (currentstate == HAL_OSPI_STATE_BUSY_CMD)
+ {
+ /* Command complete callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->CmdCpltCallback(hospi);
+#else
+ HAL_OSPI_CmdCpltCallback(hospi);
+#endif
+ }
+ else if (currentstate == HAL_OSPI_STATE_ABORT)
+ {
+ if (hospi->ErrorCode == HAL_OSPI_ERROR_NONE)
+ {
+ /* Abort called by the user */
+ /* Abort complete callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->AbortCpltCallback(hospi);
+#else
+ HAL_OSPI_AbortCpltCallback(hospi);
+#endif
+ }
+ else
+ {
+ /* Abort due to an error (eg : DMA error) */
+ /* Error callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->ErrorCallback(hospi);
+#else
+ HAL_OSPI_ErrorCallback(hospi);
+#endif
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+ /* OctoSPI status match interrupt occurred ---------------------------------*/
+ else if (((flag & HAL_OSPI_FLAG_SM) != 0U) && ((itsource & HAL_OSPI_IT_SM) != 0U))
+ {
+ /* Clear flag */
+ hospi->Instance->FCR = HAL_OSPI_FLAG_SM;
+
+ /* Check if automatic poll mode stop is activated */
+ if ((hospi->Instance->CR & OCTOSPI_CR_APMS) != 0U)
+ {
+ /* Disable the interrupts */
+ __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_SM | HAL_OSPI_IT_TE);
+
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+
+ /* Status match callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->StatusMatchCallback(hospi);
+#else
+ HAL_OSPI_StatusMatchCallback(hospi);
+#endif
+ }
+ /* OctoSPI transfer error interrupt occurred -------------------------------*/
+ else if (((flag & HAL_OSPI_FLAG_TE) != 0U) && ((itsource & HAL_OSPI_IT_TE) != 0U))
+ {
+ /* Clear flag */
+ hospi->Instance->FCR = HAL_OSPI_FLAG_TE;
+
+ /* Disable all interrupts */
+ __HAL_OSPI_DISABLE_IT(hospi, (HAL_OSPI_IT_TO | HAL_OSPI_IT_SM | HAL_OSPI_IT_FT | HAL_OSPI_IT_TC | HAL_OSPI_IT_TE));
+
+ /* Set error code */
+ hospi->ErrorCode = HAL_OSPI_ERROR_TRANSFER;
+
+ /* Check if the DMA is enabled */
+ if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U)
+ {
+ /* Disable the DMA transfer on the OctoSPI side */
+ CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
+
+ /* Disable the DMA transfer on the DMA side */
+ hospi->hmdma->XferAbortCallback = OSPI_DMAAbortCplt;
+ if (HAL_MDMA_Abort_IT(hospi->hmdma) != HAL_OK)
+ {
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+
+ /* Error callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->ErrorCallback(hospi);
+#else
+ HAL_OSPI_ErrorCallback(hospi);
+#endif
+ }
+ }
+ else
+ {
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+
+ /* Error callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->ErrorCallback(hospi);
+#else
+ HAL_OSPI_ErrorCallback(hospi);
+#endif
+ }
+ }
+ /* OctoSPI timeout interrupt occurred --------------------------------------*/
+ else if (((flag & HAL_OSPI_FLAG_TO) != 0U) && ((itsource & HAL_OSPI_IT_TO) != 0U))
+ {
+ /* Clear flag */
+ hospi->Instance->FCR = HAL_OSPI_FLAG_TO;
+
+ /* Timeout callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->TimeOutCallback(hospi);
+#else
+ HAL_OSPI_TimeOutCallback(hospi);
+#endif
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief Set the command configuration.
+ * @param hospi : OSPI handle
+ * @param cmd : structure that contains the command configuration information
+ * @param Timeout : Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_Command(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+ uint32_t state;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters of the command structure */
+ assert_param(IS_OSPI_OPERATION_TYPE(cmd->OperationType));
+
+ if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE)
+ {
+ assert_param(IS_OSPI_FLASH_ID(cmd->FlashId));
+ }
+
+ assert_param(IS_OSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_OSPI_INSTRUCTION_SIZE (cmd->InstructionSize));
+ assert_param(IS_OSPI_INSTRUCTION_DTR_MODE(cmd->InstructionDtrMode));
+ }
+
+ assert_param(IS_OSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_OSPI_ADDRESS_SIZE (cmd->AddressSize));
+ assert_param(IS_OSPI_ADDRESS_DTR_MODE(cmd->AddressDtrMode));
+ }
+
+ assert_param(IS_OSPI_ALT_BYTES_MODE(cmd->AlternateBytesMode));
+ if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_OSPI_ALT_BYTES_SIZE (cmd->AlternateBytesSize));
+ assert_param(IS_OSPI_ALT_BYTES_DTR_MODE(cmd->AlternateBytesDtrMode));
+ }
+
+ assert_param(IS_OSPI_DATA_MODE(cmd->DataMode));
+ if (cmd->DataMode != HAL_OSPI_DATA_NONE)
+ {
+ if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG)
+ {
+ assert_param(IS_OSPI_NUMBER_DATA (cmd->NbData));
+ }
+ assert_param(IS_OSPI_DATA_DTR_MODE(cmd->DataDtrMode));
+ assert_param(IS_OSPI_DUMMY_CYCLES (cmd->DummyCycles));
+ }
+
+ assert_param(IS_OSPI_DQS_MODE (cmd->DQSMode));
+ assert_param(IS_OSPI_SIOO_MODE(cmd->SIOOMode));
+
+ /* Check the state of the driver */
+ state = hospi->State;
+ if (((state == HAL_OSPI_STATE_READY) && (hospi->Init.MemoryType != HAL_OSPI_MEMTYPE_HYPERBUS)) ||
+ ((state == HAL_OSPI_STATE_READ_CMD_CFG) && ((cmd->OperationType == HAL_OSPI_OPTYPE_WRITE_CFG) || (cmd->OperationType == HAL_OSPI_OPTYPE_WRAP_CFG))) ||
+ ((state == HAL_OSPI_STATE_WRITE_CMD_CFG) && ((cmd->OperationType == HAL_OSPI_OPTYPE_READ_CFG) || (cmd->OperationType == HAL_OSPI_OPTYPE_WRAP_CFG))))
+ {
+ /* Wait till busy flag is reset */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Initialize error code */
+ hospi->ErrorCode = HAL_OSPI_ERROR_NONE;
+
+ /* Configure the registers */
+ status = OSPI_ConfigCmd(hospi, cmd);
+
+ if (status == HAL_OK)
+ {
+ if (cmd->DataMode == HAL_OSPI_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 = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout);
+
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
+ }
+ else
+ {
+ /* Update the state */
+ if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG)
+ {
+ hospi->State = HAL_OSPI_STATE_CMD_CFG;
+ }
+ else if (cmd->OperationType == HAL_OSPI_OPTYPE_READ_CFG)
+ {
+ if (hospi->State == HAL_OSPI_STATE_WRITE_CMD_CFG)
+ {
+ hospi->State = HAL_OSPI_STATE_CMD_CFG;
+ }
+ else
+ {
+ hospi->State = HAL_OSPI_STATE_READ_CMD_CFG;
+ }
+ }
+ else if (cmd->OperationType == HAL_OSPI_OPTYPE_WRITE_CFG)
+ {
+ if (hospi->State == HAL_OSPI_STATE_READ_CMD_CFG)
+ {
+ hospi->State = HAL_OSPI_STATE_CMD_CFG;
+ }
+ else
+ {
+ hospi->State = HAL_OSPI_STATE_WRITE_CMD_CFG;
+ }
+ }
+ else
+ {
+ /* Wrap configuration, no state change */
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Set the command configuration in interrupt mode.
+ * @param hospi : OSPI 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_OSPI_Command_IT(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters of the command structure */
+ assert_param(IS_OSPI_OPERATION_TYPE(cmd->OperationType));
+
+ if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE)
+ {
+ assert_param(IS_OSPI_FLASH_ID(cmd->FlashId));
+ }
+
+ assert_param(IS_OSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_OSPI_INSTRUCTION_SIZE (cmd->InstructionSize));
+ assert_param(IS_OSPI_INSTRUCTION_DTR_MODE(cmd->InstructionDtrMode));
+ }
+
+ assert_param(IS_OSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_OSPI_ADDRESS_SIZE (cmd->AddressSize));
+ assert_param(IS_OSPI_ADDRESS_DTR_MODE(cmd->AddressDtrMode));
+ }
+
+ assert_param(IS_OSPI_ALT_BYTES_MODE(cmd->AlternateBytesMode));
+ if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_OSPI_ALT_BYTES_SIZE (cmd->AlternateBytesSize));
+ assert_param(IS_OSPI_ALT_BYTES_DTR_MODE(cmd->AlternateBytesDtrMode));
+ }
+
+ assert_param(IS_OSPI_DATA_MODE(cmd->DataMode));
+ if (cmd->DataMode != HAL_OSPI_DATA_NONE)
+ {
+ assert_param(IS_OSPI_NUMBER_DATA (cmd->NbData));
+ assert_param(IS_OSPI_DATA_DTR_MODE(cmd->DataDtrMode));
+ assert_param(IS_OSPI_DUMMY_CYCLES (cmd->DummyCycles));
+ }
+
+ assert_param(IS_OSPI_DQS_MODE (cmd->DQSMode));
+ assert_param(IS_OSPI_SIOO_MODE(cmd->SIOOMode));
+
+ /* Check the state of the driver */
+ if ((hospi->State == HAL_OSPI_STATE_READY) && (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG) &&
+ (cmd->DataMode == HAL_OSPI_DATA_NONE) && (hospi->Init.MemoryType != HAL_OSPI_MEMTYPE_HYPERBUS))
+ {
+ /* Wait till busy flag is reset */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Initialize error code */
+ hospi->ErrorCode = HAL_OSPI_ERROR_NONE;
+
+ /* Clear flags related to interrupt */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
+
+ /* Configure the registers */
+ status = OSPI_ConfigCmd(hospi, cmd);
+
+ if (status == HAL_OK)
+ {
+ /* Update the state */
+ hospi->State = HAL_OSPI_STATE_BUSY_CMD;
+
+ /* Enable the transfer complete and transfer error interrupts */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_TE);
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Configure the Hyperbus parameters.
+ * @param hospi : OSPI handle
+ * @param cfg : Structure containing the Hyperbus configuration
+ * @param Timeout : Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_HyperbusCfg(OSPI_HandleTypeDef *hospi, OSPI_HyperbusCfgTypeDef *cfg, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+ uint32_t state;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters of the hyperbus configuration structure */
+ assert_param(IS_OSPI_RW_RECOVERY_TIME (cfg->RWRecoveryTime));
+ assert_param(IS_OSPI_ACCESS_TIME (cfg->AccessTime));
+ assert_param(IS_OSPI_WRITE_ZERO_LATENCY(cfg->WriteZeroLatency));
+ assert_param(IS_OSPI_LATENCY_MODE (cfg->LatencyMode));
+
+ /* Check the state of the driver */
+ state = hospi->State;
+ if ((state == HAL_OSPI_STATE_HYPERBUS_INIT) || (state == HAL_OSPI_STATE_READY))
+ {
+ /* Wait till busy flag is reset */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure Hyperbus configuration Latency register */
+ WRITE_REG(hospi->Instance->HLCR, ((cfg->RWRecoveryTime << OCTOSPI_HLCR_TRWR_Pos) |
+ (cfg->AccessTime << OCTOSPI_HLCR_TACC_Pos) |
+ cfg->WriteZeroLatency | cfg->LatencyMode));
+
+ /* Update the state */
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Set the Hyperbus command configuration.
+ * @param hospi : OSPI handle
+ * @param cmd : Structure containing the Hyperbus command
+ * @param Timeout : Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_HyperbusCmd(OSPI_HandleTypeDef *hospi, OSPI_HyperbusCmdTypeDef *cmd, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters of the hyperbus command structure */
+ assert_param(IS_OSPI_ADDRESS_SPACE(cmd->AddressSpace));
+ assert_param(IS_OSPI_ADDRESS_SIZE (cmd->AddressSize));
+ assert_param(IS_OSPI_NUMBER_DATA (cmd->NbData));
+ assert_param(IS_OSPI_DQS_MODE (cmd->DQSMode));
+
+ /* Check the state of the driver */
+ if ((hospi->State == HAL_OSPI_STATE_READY) && (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS))
+ {
+ /* Wait till busy flag is reset */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Re-initialize the value of the functional mode */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, 0U);
+
+ /* Configure the address space in the DCR1 register */
+ MODIFY_REG(hospi->Instance->DCR1, OCTOSPI_DCR1_MTYP_0, cmd->AddressSpace);
+
+ /* Configure the CCR and WCCR registers with the address size and the following configuration :
+ - DQS signal enabled (used as RWDS)
+ - DTR mode enabled on address and data
+ - address and data on 8 lines */
+ WRITE_REG(hospi->Instance->CCR, (cmd->DQSMode | OCTOSPI_CCR_DDTR | OCTOSPI_CCR_DMODE_2 |
+ cmd->AddressSize | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADMODE_2));
+ WRITE_REG(hospi->Instance->WCCR, (cmd->DQSMode | OCTOSPI_WCCR_DDTR | OCTOSPI_WCCR_DMODE_2 |
+ cmd->AddressSize | OCTOSPI_WCCR_ADDTR | OCTOSPI_WCCR_ADMODE_2));
+
+ /* Configure the DLR register with the number of data */
+ WRITE_REG(hospi->Instance->DLR, (cmd->NbData - 1U));
+
+ /* Configure the AR register with the address value */
+ WRITE_REG(hospi->Instance->AR, cmd->Address);
+
+ /* Update the state */
+ hospi->State = HAL_OSPI_STATE_CMD_CFG;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Transmit an amount of data in blocking mode.
+ * @param hospi : OSPI 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_OSPI_Transmit(OSPI_HandleTypeDef *hospi, uint8_t *pData, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+ __IO uint32_t *data_reg = &hospi->Instance->DR;
+
+ /* Check the data pointer allocation */
+ if (pData == NULL)
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ /* Check the state */
+ if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
+ {
+ /* Configure counters and size */
+ hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
+ hospi->XferSize = hospi->XferCount;
+ hospi->pBuffPtr = pData;
+
+ /* Configure CR register with functional mode as indirect write */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ do
+ {
+ /* Wait till fifo threshold flag is set to send data */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_FT, SET, tickstart, Timeout);
+
+ if (status != HAL_OK)
+ {
+ break;
+ }
+
+ *((__IO uint8_t *)data_reg) = *hospi->pBuffPtr;
+ hospi->pBuffPtr++;
+ hospi->XferCount--;
+ } while (hospi->XferCount > 0U);
+
+ if (status == HAL_OK)
+ {
+ /* Wait till transfer complete flag is set to go back in idle state */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Clear transfer complete flag */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
+
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param hospi : OSPI 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_OSPI_Receive(OSPI_HandleTypeDef *hospi, uint8_t *pData, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+ __IO uint32_t *data_reg = &hospi->Instance->DR;
+ uint32_t addr_reg = hospi->Instance->AR;
+ uint32_t ir_reg = hospi->Instance->IR;
+
+ /* Check the data pointer allocation */
+ if (pData == NULL)
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ /* Check the state */
+ if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
+ {
+ /* Configure counters and size */
+ hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
+ hospi->XferSize = hospi->XferCount;
+ hospi->pBuffPtr = pData;
+
+ /* Configure CR register with functional mode as indirect read */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);
+
+ /* Trig the transfer by re-writing address or instruction register */
+ if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ WRITE_REG(hospi->Instance->IR, ir_reg);
+ }
+ }
+
+ do
+ {
+ /* Wait till fifo threshold or transfer complete flags are set to read received data */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, (HAL_OSPI_FLAG_FT | HAL_OSPI_FLAG_TC), SET, tickstart, Timeout);
+
+ if (status != HAL_OK)
+ {
+ break;
+ }
+
+ *hospi->pBuffPtr = *((__IO uint8_t *)data_reg);
+ hospi->pBuffPtr++;
+ hospi->XferCount--;
+ } while(hospi->XferCount > 0U);
+
+ if (status == HAL_OK)
+ {
+ /* Wait till transfer complete flag is set to go back in idle state */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Clear transfer complete flag */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
+
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Send an amount of data in non-blocking mode with interrupt.
+ * @param hospi : OSPI handle
+ * @param pData : pointer to data buffer
+ * @note This function is used only in Indirect Write Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_Transmit_IT(OSPI_HandleTypeDef *hospi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the data pointer allocation */
+ if (pData == NULL)
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ /* Check the state */
+ if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
+ {
+ /* Configure counters and size */
+ hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
+ hospi->XferSize = hospi->XferCount;
+ hospi->pBuffPtr = pData;
+
+ /* Configure CR register with functional mode as indirect write */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ /* Clear flags related to interrupt */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
+
+ /* Update the state */
+ hospi->State = HAL_OSPI_STATE_BUSY_TX;
+
+ /* Enable the transfer complete, fifo threshold and transfer error interrupts */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with interrupt.
+ * @param hospi : OSPI handle
+ * @param pData : pointer to data buffer
+ * @note This function is used only in Indirect Read Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_Receive_IT(OSPI_HandleTypeDef *hospi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t addr_reg = hospi->Instance->AR;
+ uint32_t ir_reg = hospi->Instance->IR;
+
+ /* Check the data pointer allocation */
+ if (pData == NULL)
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ /* Check the state */
+ if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
+ {
+ /* Configure counters and size */
+ hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
+ hospi->XferSize = hospi->XferCount;
+ hospi->pBuffPtr = pData;
+
+ /* Configure CR register with functional mode as indirect read */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);
+
+ /* Clear flags related to interrupt */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
+
+ /* Update the state */
+ hospi->State = HAL_OSPI_STATE_BUSY_RX;
+
+ /* Enable the transfer complete, fifo threshold and transfer error interrupts */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
+
+ /* Trig the transfer by re-writing address or instruction register */
+ if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ WRITE_REG(hospi->Instance->IR, ir_reg);
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Send an amount of data in non-blocking mode with DMA.
+ * @param hospi : OSPI handle
+ * @param pData : pointer to data buffer
+ * @note This function is used only in Indirect Write Mode
+ * @note If DMA peripheral access is configured as halfword, the number
+ * of data and the fifo threshold should be aligned on halfword
+ * @note If DMA peripheral access is configured as word, the number
+ * of data and the fifo threshold should be aligned on word
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_Transmit_DMA(OSPI_HandleTypeDef *hospi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t data_size = hospi->Instance->DLR + 1U;
+
+ /* Check the data pointer allocation */
+ if (pData == NULL)
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ /* Check the state */
+ if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
+ {
+ hospi->XferCount = data_size;
+
+ {
+ hospi->XferSize = hospi->XferCount;
+ hospi->pBuffPtr = pData;
+
+ /* Configure CR register with functional mode as indirect write */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ /* Clear flags related to interrupt */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
+
+ /* Update the state */
+ hospi->State = HAL_OSPI_STATE_BUSY_TX;
+
+ /* Set the MDMA transfer complete callback */
+ hospi->hmdma->XferCpltCallback = OSPI_DMACplt;
+
+ /* Set the MDMA error callback */
+ hospi->hmdma->XferErrorCallback = OSPI_DMAError;
+
+ /* Clear the MDMA abort callback */
+ hospi->hmdma->XferAbortCallback = NULL;
+
+ /* In Transmit mode , the MDMA destination is the OSPI DR register : Force the MDMA Destination Increment to disable */
+ MODIFY_REG(hospi->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 (hospi->hmdma->Init.SourceDataSize == MDMA_SRC_DATASIZE_BYTE)
+ {
+ MODIFY_REG(hospi->hmdma->Instance->CTCR, (MDMA_CTCR_SINC | MDMA_CTCR_SINCOS) , MDMA_SRC_INC_BYTE);
+ }
+ else if (hospi->hmdma->Init.SourceDataSize == MDMA_SRC_DATASIZE_HALFWORD)
+ {
+ MODIFY_REG(hospi->hmdma->Instance->CTCR, (MDMA_CTCR_SINC | MDMA_CTCR_SINCOS) , MDMA_SRC_INC_HALFWORD);
+ }
+ else if (hospi->hmdma->Init.SourceDataSize == MDMA_SRC_DATASIZE_WORD)
+ {
+ MODIFY_REG(hospi->hmdma->Instance->CTCR, (MDMA_CTCR_SINC | MDMA_CTCR_SINCOS) , MDMA_SRC_INC_WORD);
+ }
+ else
+ {
+ /* in case of incorrect source data size */
+ hospi->ErrorCode |= HAL_OSPI_ERROR_DMA;
+ status = HAL_ERROR;
+ }
+
+ /* Enable the transmit MDMA Channel */
+ if (HAL_MDMA_Start_IT(hospi->hmdma, (uint32_t)pData, (uint32_t)&hospi->Instance->DR, hospi->XferSize,1) == HAL_OK)
+ {
+ /* Enable the transfer error interrupt */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TE);
+
+ /* Enable the MDMA transfer by setting the DMAEN bit not needed for MDMA*/
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA.
+ * @param hospi : OSPI handle
+ * @param pData : pointer to data buffer.
+ * @note This function is used only in Indirect Read Mode
+ * @note If DMA peripheral access is configured as halfword, the number
+ * of data and the fifo threshold should be aligned on halfword
+ * @note If DMA peripheral access is configured as word, the number
+ * of data and the fifo threshold should be aligned on word
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_Receive_DMA(OSPI_HandleTypeDef *hospi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t data_size = hospi->Instance->DLR + 1U;
+ uint32_t addr_reg = hospi->Instance->AR;
+ uint32_t ir_reg = hospi->Instance->IR;
+
+ /* Check the data pointer allocation */
+ if (pData == NULL)
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
+ }
+ else
+ {
+ /* Check the state */
+ if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
+ {
+ hospi->XferCount = data_size;
+
+ {
+ hospi->XferSize = hospi->XferCount;
+ hospi->pBuffPtr = pData;
+
+ /* Configure CR register with functional mode as indirect read */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);
+
+ /* Clear flags related to interrupt */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
+
+ /* Update the state */
+ hospi->State = HAL_OSPI_STATE_BUSY_RX;
+
+ /* Set the DMA transfer complete callback */
+ hospi->hmdma->XferCpltCallback = OSPI_DMACplt;
+
+ /* Set the DMA error callback */
+ hospi->hmdma->XferErrorCallback = OSPI_DMAError;
+
+ /* Clear the DMA abort callback */
+ hospi->hmdma->XferAbortCallback = NULL;
+
+/* In Receive mode , the MDMA source is the OSPI DR register : Force the MDMA Source Increment to disable */
+ MODIFY_REG(hospi->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 (hospi->hmdma->Init.DestDataSize == MDMA_DEST_DATASIZE_BYTE)
+ {
+ MODIFY_REG(hospi->hmdma->Instance->CTCR, (MDMA_CTCR_DINC | MDMA_CTCR_DINCOS) , MDMA_DEST_INC_BYTE);
+ }
+ else if (hospi->hmdma->Init.DestDataSize == MDMA_DEST_DATASIZE_HALFWORD)
+ {
+ MODIFY_REG(hospi->hmdma->Instance->CTCR, (MDMA_CTCR_DINC | MDMA_CTCR_DINCOS) , MDMA_DEST_INC_HALFWORD);
+ }
+ else if (hospi->hmdma->Init.DestDataSize == MDMA_DEST_DATASIZE_WORD)
+ {
+ MODIFY_REG(hospi->hmdma->Instance->CTCR, (MDMA_CTCR_DINC | MDMA_CTCR_DINCOS) , MDMA_DEST_INC_WORD);
+ }
+ else
+ {
+ /* in case of incorrect destination data size */
+ hospi->ErrorCode |= HAL_OSPI_ERROR_DMA;
+ status = HAL_ERROR;
+ }
+
+ /* Enable the transmit MDMA Channel */
+ if (HAL_MDMA_Start_IT(hospi->hmdma, (uint32_t)&hospi->Instance->DR, (uint32_t)pData, hospi->XferSize, 1) == HAL_OK)
+ {
+ /* Enable the transfer error interrupt */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TE);
+
+ /* Trig the transfer by re-writing address or instruction register */
+ if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ WRITE_REG(hospi->Instance->IR, ir_reg);
+ }
+ }
+
+ /* Enable the MDMA transfer by setting the DMAEN bit not needed for MDMA*/
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Configure the OSPI Automatic Polling Mode in blocking mode.
+ * @param hospi : OSPI handle
+ * @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_OSPI_AutoPolling(OSPI_HandleTypeDef *hospi, OSPI_AutoPollingTypeDef *cfg, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t addr_reg = hospi->Instance->AR;
+ uint32_t ir_reg = hospi->Instance->IR;
+#ifdef USE_FULL_ASSERT
+ uint32_t dlr_reg = hospi->Instance->DLR;
+#endif
+
+ /* Check the parameters of the autopolling configuration structure */
+ assert_param(IS_OSPI_MATCH_MODE (cfg->MatchMode));
+ assert_param(IS_OSPI_AUTOMATIC_STOP (cfg->AutomaticStop));
+ assert_param(IS_OSPI_INTERVAL (cfg->Interval));
+ assert_param(IS_OSPI_STATUS_BYTES_SIZE(dlr_reg+1U));
+
+ /* Check the state */
+ if ((hospi->State == HAL_OSPI_STATE_CMD_CFG) && (cfg->AutomaticStop == HAL_OSPI_AUTOMATIC_STOP_ENABLE))
+ {
+ /* Wait till busy flag is reset */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure registers */
+ WRITE_REG (hospi->Instance->PSMAR, cfg->Match);
+ WRITE_REG (hospi->Instance->PSMKR, cfg->Mask);
+ WRITE_REG (hospi->Instance->PIR, cfg->Interval);
+ MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_PMM | OCTOSPI_CR_APMS | OCTOSPI_CR_FMODE),
+ (cfg->MatchMode | cfg->AutomaticStop | OSPI_FUNCTIONAL_MODE_AUTO_POLLING));
+
+ /* Trig the transfer by re-writing address or instruction register */
+ if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ WRITE_REG(hospi->Instance->IR, ir_reg);
+ }
+ }
+
+ /* Wait till status match flag is set to go back in idle state */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_SM, SET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Clear status match flag */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_SM);
+
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Configure the OSPI Automatic Polling Mode in non-blocking mode.
+ * @param hospi : OSPI handle
+ * @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_OSPI_AutoPolling_IT(OSPI_HandleTypeDef *hospi, OSPI_AutoPollingTypeDef *cfg)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t addr_reg = hospi->Instance->AR;
+ uint32_t ir_reg = hospi->Instance->IR;
+#ifdef USE_FULL_ASSERT
+ uint32_t dlr_reg = hospi->Instance->DLR;
+#endif
+
+ /* Check the parameters of the autopolling configuration structure */
+ assert_param(IS_OSPI_MATCH_MODE (cfg->MatchMode));
+ assert_param(IS_OSPI_AUTOMATIC_STOP (cfg->AutomaticStop));
+ assert_param(IS_OSPI_INTERVAL (cfg->Interval));
+ assert_param(IS_OSPI_STATUS_BYTES_SIZE(dlr_reg+1U));
+
+ /* Check the state */
+ if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
+ {
+ /* Wait till busy flag is reset */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure registers */
+ WRITE_REG (hospi->Instance->PSMAR, cfg->Match);
+ WRITE_REG (hospi->Instance->PSMKR, cfg->Mask);
+ WRITE_REG (hospi->Instance->PIR, cfg->Interval);
+ MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_PMM | OCTOSPI_CR_APMS | OCTOSPI_CR_FMODE),
+ (cfg->MatchMode | cfg->AutomaticStop | OSPI_FUNCTIONAL_MODE_AUTO_POLLING));
+
+ /* Clear flags related to interrupt */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_SM);
+
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_BUSY_AUTO_POLLING;
+
+ /* Enable the status match and transfer error interrupts */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_SM | HAL_OSPI_IT_TE);
+
+ /* Trig the transfer by re-writing address or instruction register */
+ if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
+ {
+ WRITE_REG(hospi->Instance->AR, addr_reg);
+ }
+ else
+ {
+ WRITE_REG(hospi->Instance->IR, ir_reg);
+ }
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Configure the Memory Mapped mode.
+ * @param hospi : OSPI handle
+ * @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_OSPI_MemoryMapped(OSPI_HandleTypeDef *hospi, OSPI_MemoryMappedTypeDef *cfg)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters of the memory-mapped configuration structure */
+ assert_param(IS_OSPI_TIMEOUT_ACTIVATION(cfg->TimeOutActivation));
+
+ /* Check the state */
+ if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
+ {
+ /* Wait till busy flag is reset */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_BUSY_MEM_MAPPED;
+
+ if (cfg->TimeOutActivation == HAL_OSPI_TIMEOUT_COUNTER_ENABLE)
+ {
+ assert_param(IS_OSPI_TIMEOUT_PERIOD(cfg->TimeOutPeriod));
+
+ /* Configure register */
+ WRITE_REG(hospi->Instance->LPTR, cfg->TimeOutPeriod);
+
+ /* Clear flags related to interrupt */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TO);
+
+ /* Enable the timeout interrupt */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TO);
+ }
+
+ /* Configure CR register with functional mode as memory-mapped */
+ MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_TCEN | OCTOSPI_CR_FMODE),
+ (cfg->TimeOutActivation | OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED));
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Transfer Error callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_ErrorCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_OSPI_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Abort completed callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_AbortCpltCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_OSPI_AbortCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief FIFO Threshold callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_FifoThresholdCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_OSPI_FIFOThresholdCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Command completed callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_CmdCpltCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_OSPI_CmdCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_RxCpltCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_OSPI_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+ __weak void HAL_OSPI_TxCpltCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_OSPI_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Half Transfer completed callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_RxHalfCpltCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_OSPI_RxHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_TxHalfCpltCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_OSPI_TxHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Status Match callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_StatusMatchCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_OSPI_StatusMatchCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Timeout callback.
+ * @param hospi : OSPI handle
+ * @retval None
+ */
+__weak void HAL_OSPI_TimeOutCallback(OSPI_HandleTypeDef *hospi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hospi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_OSPI_TimeOutCallback could be implemented in the user file
+ */
+}
+
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+/**
+ * @brief Register a User OSPI Callback
+ * To be used instead of the weak (surcharged) predefined callback
+ * @param hospi : OSPI handle
+ * @param CallbackID : ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_OSPI_ERROR_CB_ID OSPI Error Callback ID
+ * @arg @ref HAL_OSPI_ABORT_CB_ID OSPI Abort Callback ID
+ * @arg @ref HAL_OSPI_FIFO_THRESHOLD_CB_ID OSPI FIFO Threshold Callback ID
+ * @arg @ref HAL_OSPI_CMD_CPLT_CB_ID OSPI Command Complete Callback ID
+ * @arg @ref HAL_OSPI_RX_CPLT_CB_ID OSPI Rx Complete Callback ID
+ * @arg @ref HAL_OSPI_TX_CPLT_CB_ID OSPI Tx Complete Callback ID
+ * @arg @ref HAL_OSPI_RX_HALF_CPLT_CB_ID OSPI Rx Half Complete Callback ID
+ * @arg @ref HAL_OSPI_TX_HALF_CPLT_CB_ID OSPI Tx Half Complete Callback ID
+ * @arg @ref HAL_OSPI_STATUS_MATCH_CB_ID OSPI Status Match Callback ID
+ * @arg @ref HAL_OSPI_TIMEOUT_CB_ID OSPI Timeout Callback ID
+ * @arg @ref HAL_OSPI_MSP_INIT_CB_ID OSPI MspInit callback ID
+ * @arg @ref HAL_OSPI_MSP_DEINIT_CB_ID OSPI MspDeInit callback ID
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_OSPI_RegisterCallback (OSPI_HandleTypeDef *hospi, HAL_OSPI_CallbackIDTypeDef CallbackID, pOSPI_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ if(hospi->State == HAL_OSPI_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_OSPI_ERROR_CB_ID :
+ hospi->ErrorCallback = pCallback;
+ break;
+ case HAL_OSPI_ABORT_CB_ID :
+ hospi->AbortCpltCallback = pCallback;
+ break;
+ case HAL_OSPI_FIFO_THRESHOLD_CB_ID :
+ hospi->FifoThresholdCallback = pCallback;
+ break;
+ case HAL_OSPI_CMD_CPLT_CB_ID :
+ hospi->CmdCpltCallback = pCallback;
+ break;
+ case HAL_OSPI_RX_CPLT_CB_ID :
+ hospi->RxCpltCallback = pCallback;
+ break;
+ case HAL_OSPI_TX_CPLT_CB_ID :
+ hospi->TxCpltCallback = pCallback;
+ break;
+ case HAL_OSPI_RX_HALF_CPLT_CB_ID :
+ hospi->RxHalfCpltCallback = pCallback;
+ break;
+ case HAL_OSPI_TX_HALF_CPLT_CB_ID :
+ hospi->TxHalfCpltCallback = pCallback;
+ break;
+ case HAL_OSPI_STATUS_MATCH_CB_ID :
+ hospi->StatusMatchCallback = pCallback;
+ break;
+ case HAL_OSPI_TIMEOUT_CB_ID :
+ hospi->TimeOutCallback = pCallback;
+ break;
+ case HAL_OSPI_MSP_INIT_CB_ID :
+ hospi->MspInitCallback = pCallback;
+ break;
+ case HAL_OSPI_MSP_DEINIT_CB_ID :
+ hospi->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hospi->State == HAL_OSPI_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_OSPI_MSP_INIT_CB_ID :
+ hospi->MspInitCallback = pCallback;
+ break;
+ case HAL_OSPI_MSP_DEINIT_CB_ID :
+ hospi->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a User OSPI Callback
+ * OSPI Callback is redirected to the weak (surcharged) predefined callback
+ * @param hospi : OSPI handle
+ * @param CallbackID : ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_OSPI_ERROR_CB_ID OSPI Error Callback ID
+ * @arg @ref HAL_OSPI_ABORT_CB_ID OSPI Abort Callback ID
+ * @arg @ref HAL_OSPI_FIFO_THRESHOLD_CB_ID OSPI FIFO Threshold Callback ID
+ * @arg @ref HAL_OSPI_CMD_CPLT_CB_ID OSPI Command Complete Callback ID
+ * @arg @ref HAL_OSPI_RX_CPLT_CB_ID OSPI Rx Complete Callback ID
+ * @arg @ref HAL_OSPI_TX_CPLT_CB_ID OSPI Tx Complete Callback ID
+ * @arg @ref HAL_OSPI_RX_HALF_CPLT_CB_ID OSPI Rx Half Complete Callback ID
+ * @arg @ref HAL_OSPI_TX_HALF_CPLT_CB_ID OSPI Tx Half Complete Callback ID
+ * @arg @ref HAL_OSPI_STATUS_MATCH_CB_ID OSPI Status Match Callback ID
+ * @arg @ref HAL_OSPI_TIMEOUT_CB_ID OSPI Timeout Callback ID
+ * @arg @ref HAL_OSPI_MSP_INIT_CB_ID OSPI MspInit callback ID
+ * @arg @ref HAL_OSPI_MSP_DEINIT_CB_ID OSPI MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_OSPI_UnRegisterCallback (OSPI_HandleTypeDef *hospi, HAL_OSPI_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(hospi->State == HAL_OSPI_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_OSPI_ERROR_CB_ID :
+ hospi->ErrorCallback = HAL_OSPI_ErrorCallback;
+ break;
+ case HAL_OSPI_ABORT_CB_ID :
+ hospi->AbortCpltCallback = HAL_OSPI_AbortCpltCallback;
+ break;
+ case HAL_OSPI_FIFO_THRESHOLD_CB_ID :
+ hospi->FifoThresholdCallback = HAL_OSPI_FifoThresholdCallback;
+ break;
+ case HAL_OSPI_CMD_CPLT_CB_ID :
+ hospi->CmdCpltCallback = HAL_OSPI_CmdCpltCallback;
+ break;
+ case HAL_OSPI_RX_CPLT_CB_ID :
+ hospi->RxCpltCallback = HAL_OSPI_RxCpltCallback;
+ break;
+ case HAL_OSPI_TX_CPLT_CB_ID :
+ hospi->TxCpltCallback = HAL_OSPI_TxCpltCallback;
+ break;
+ case HAL_OSPI_RX_HALF_CPLT_CB_ID :
+ hospi->RxHalfCpltCallback = HAL_OSPI_RxHalfCpltCallback;
+ break;
+ case HAL_OSPI_TX_HALF_CPLT_CB_ID :
+ hospi->TxHalfCpltCallback = HAL_OSPI_TxHalfCpltCallback;
+ break;
+ case HAL_OSPI_STATUS_MATCH_CB_ID :
+ hospi->StatusMatchCallback = HAL_OSPI_StatusMatchCallback;
+ break;
+ case HAL_OSPI_TIMEOUT_CB_ID :
+ hospi->TimeOutCallback = HAL_OSPI_TimeOutCallback;
+ break;
+ case HAL_OSPI_MSP_INIT_CB_ID :
+ hospi->MspInitCallback = HAL_OSPI_MspInit;
+ break;
+ case HAL_OSPI_MSP_DEINIT_CB_ID :
+ hospi->MspDeInitCallback = HAL_OSPI_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hospi->State == HAL_OSPI_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_OSPI_MSP_INIT_CB_ID :
+ hospi->MspInitCallback = HAL_OSPI_MspInit;
+ break;
+ case HAL_OSPI_MSP_DEINIT_CB_ID :
+ hospi->MspDeInitCallback = HAL_OSPI_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+#endif
+
+/**
+ * @}
+ */
+
+/** @defgroup OSPI_Exported_Functions_Group3 Peripheral Control and State functions
+ * @brief OSPI 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.
+ (+) Manage the Fifo threshold.
+ (+) Configure the timeout duration used in the driver.
+
+@endverbatim
+ * @{
+ */
+
+/**
+* @brief Abort the current transmission.
+* @param hospi : OSPI handle
+* @retval HAL status
+*/
+HAL_StatusTypeDef HAL_OSPI_Abort(OSPI_HandleTypeDef *hospi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t state;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check if the state is in one of the busy or configured states */
+ state = hospi->State;
+ if (((state & OSPI_BUSY_STATE_MASK) != 0U) || ((state & OSPI_CFG_STATE_MASK) != 0U))
+ {
+ /* Check if the DMA is enabled */
+ if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U)
+ {
+ /* Disable the DMA transfer on the OctoSPI side */
+ CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
+
+ /* Disable the DMA transfer on the DMA side */
+ status = HAL_MDMA_Abort(hospi->hmdma);
+ if (status != HAL_OK)
+ {
+ hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
+ }
+ }
+
+ if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET)
+ {
+ /* Perform an abort of the OctoSPI */
+ SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT);
+
+ /* Wait until the transfer complete flag is set to go back in idle state */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, hospi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Clear transfer complete flag */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
+
+ /* Wait until the busy flag is reset to go back in idle state */
+ status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+* @brief Abort the current transmission (non-blocking function)
+* @param hospi : OSPI handle
+* @retval HAL status
+*/
+HAL_StatusTypeDef HAL_OSPI_Abort_IT(OSPI_HandleTypeDef *hospi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t state;
+
+ /* Check if the state is in one of the busy or configured states */
+ state = hospi->State;
+ if (((state & OSPI_BUSY_STATE_MASK) != 0U) || ((state & OSPI_CFG_STATE_MASK) != 0U))
+ {
+ /* Disable all interrupts */
+ __HAL_OSPI_DISABLE_IT(hospi, (HAL_OSPI_IT_TO | HAL_OSPI_IT_SM | HAL_OSPI_IT_FT | HAL_OSPI_IT_TC | HAL_OSPI_IT_TE));
+
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_ABORT;
+
+ /* Check if the DMA is enabled */
+ if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U)
+ {
+ /* Disable the DMA transfer on the OctoSPI side */
+ CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
+
+ /* Disable the DMA transfer on the DMA side */
+ hospi->hmdma->XferAbortCallback = OSPI_DMAAbortCplt;
+ if (HAL_MDMA_Abort_IT(hospi->hmdma) != HAL_OK)
+ {
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+
+ /* Abort callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->AbortCpltCallback(hospi);
+#else
+ HAL_OSPI_AbortCpltCallback(hospi);
+#endif
+ }
+ }
+ else
+ {
+ if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET)
+ {
+ /* Clear transfer complete flag */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
+
+ /* Enable the transfer complete interrupts */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC);
+
+ /* Perform an abort of the OctoSPI */
+ SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT);
+ }
+ else
+ {
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+
+ /* Abort callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->AbortCpltCallback(hospi);
+#else
+ HAL_OSPI_AbortCpltCallback(hospi);
+#endif
+ }
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/** @brief Set OSPI Fifo threshold.
+ * @param hospi : OSPI handle.
+ * @param Threshold : Threshold of the Fifo.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPI_SetFifoThreshold(OSPI_HandleTypeDef *hospi, uint32_t Threshold)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the state */
+ if ((hospi->State & OSPI_BUSY_STATE_MASK) == 0U)
+ {
+ /* Synchronize initialization structure with the new fifo threshold value */
+ hospi->Init.FifoThreshold = Threshold;
+
+ /* Configure new fifo threshold */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FTHRES, ((hospi->Init.FifoThreshold-1U) << OCTOSPI_CR_FTHRES_Pos));
+
+ }
+ else
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/** @brief Get OSPI Fifo threshold.
+ * @param hospi : OSPI handle.
+ * @retval Fifo threshold
+ */
+uint32_t HAL_OSPI_GetFifoThreshold(OSPI_HandleTypeDef *hospi)
+{
+ return ((READ_BIT(hospi->Instance->CR, OCTOSPI_CR_FTHRES) >> OCTOSPI_CR_FTHRES_Pos) + 1U);
+}
+
+/** @brief Set OSPI timeout.
+ * @param hospi : OSPI handle.
+ * @param Timeout : Timeout for the memory access.
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_OSPI_SetTimeout(OSPI_HandleTypeDef *hospi, uint32_t Timeout)
+{
+ hospi->Timeout = Timeout;
+ return HAL_OK;
+}
+
+/**
+* @brief Return the OSPI error code.
+* @param hospi : OSPI handle
+* @retval OSPI Error Code
+*/
+uint32_t HAL_OSPI_GetError(OSPI_HandleTypeDef *hospi)
+{
+ return hospi->ErrorCode;
+}
+
+/**
+ * @brief Return the OSPI handle state.
+ * @param hospi : OSPI handle
+ * @retval HAL state
+ */
+uint32_t HAL_OSPI_GetState(OSPI_HandleTypeDef *hospi)
+{
+ /* Return OSPI handle state */
+ return hospi->State;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup OSPI_Exported_Functions_Group4 IO Manager configuration function
+ * @brief OSPI IO Manager configuration function
+ *
+@verbatim
+ ===============================================================================
+ ##### IO Manager configuration function #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to :
+ (+) Configure the IO manager.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the OctoSPI IO manager.
+ * @param hospi : OSPI handle
+ * @param cfg : Configuration of the IO Manager for the instance
+ * @param Timeout : Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OSPIM_Config(OSPI_HandleTypeDef *hospi, OSPIM_CfgTypeDef *cfg, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t instance;
+ uint8_t index, ospi_enabled = 0U, other_instance;
+ OSPIM_CfgTypeDef IOM_cfg[OSPI_NB_INSTANCE];
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Timeout);
+
+ /* Check the parameters of the OctoSPI IO Manager configuration structure */
+ assert_param(IS_OSPIM_PORT(cfg->ClkPort));
+ assert_param(IS_OSPIM_PORT(cfg->DQSPort));
+ assert_param(IS_OSPIM_PORT(cfg->NCSPort));
+ assert_param(IS_OSPIM_IO_PORT(cfg->IOLowPort));
+ assert_param(IS_OSPIM_IO_PORT(cfg->IOHighPort));
+ assert_param(IS_OSPIM_REQ2ACKTIME(cfg->Req2AckTime));
+
+ if (hospi->Instance == OCTOSPI1)
+ {
+ instance = 0U;
+ other_instance = 1U;
+ }
+ else
+ {
+ instance = 1U;
+ other_instance = 0U;
+ }
+
+ /**************** Get current configuration of the instances ****************/
+ for (index = 0U; index < OSPI_NB_INSTANCE; index++)
+ {
+ if (OSPIM_GetConfig(index+1U, &(IOM_cfg[index])) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ /********** Disable both OctoSPI to configure OctoSPI IO Manager **********/
+ if ((OCTOSPI1->CR & OCTOSPI_CR_EN) != 0U)
+ {
+ CLEAR_BIT(OCTOSPI1->CR, OCTOSPI_CR_EN);
+ ospi_enabled |= 0x1U;
+ }
+ if ((OCTOSPI2->CR & OCTOSPI_CR_EN) != 0U)
+ {
+ CLEAR_BIT(OCTOSPI2->CR, OCTOSPI_CR_EN);
+ ospi_enabled |= 0x2U;
+ }
+
+ /***************** Deactivation of previous configuration *****************/
+ CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].NCSPort-1U)], OCTOSPIM_PCR_NCSEN);
+ if ((OCTOSPIM->CR & OCTOSPIM_CR_MUXEN) != 0U)
+ {
+ /* De-multiplexing should be performed */
+ CLEAR_BIT(OCTOSPIM->CR, OCTOSPIM_CR_MUXEN);
+
+ if (other_instance == 1U)
+ {
+ SET_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].ClkPort-1U)], OCTOSPIM_PCR_CLKSRC);
+ SET_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].DQSPort-1U)], OCTOSPIM_PCR_DQSSRC);
+ SET_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOLowPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOLSRC_1);
+ SET_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOHighPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOHSRC_1);
+ }
+ }
+ else
+ {
+ if (IOM_cfg[instance].ClkPort != 0U)
+ {
+ CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].ClkPort-1U)], OCTOSPIM_PCR_CLKEN);
+ CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].DQSPort-1U)], OCTOSPIM_PCR_DQSEN);
+ CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[instance].IOLowPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOLEN);
+ CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[instance].IOHighPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOHEN);
+ }
+ }
+
+ /********************* Deactivation of other instance *********************/
+ if ((cfg->ClkPort == IOM_cfg[other_instance].ClkPort) || (cfg->DQSPort == IOM_cfg[other_instance].DQSPort) ||
+ (cfg->NCSPort == IOM_cfg[other_instance].NCSPort) || (cfg->IOLowPort == IOM_cfg[other_instance].IOLowPort) ||
+ (cfg->IOHighPort == IOM_cfg[other_instance].IOHighPort))
+ {
+ if ((cfg->ClkPort == IOM_cfg[other_instance].ClkPort) && (cfg->DQSPort == IOM_cfg[other_instance].DQSPort) &&
+ (cfg->IOLowPort == IOM_cfg[other_instance].IOLowPort) && (cfg->IOHighPort == IOM_cfg[other_instance].IOHighPort))
+ {
+ /* Multiplexing should be performed */
+ SET_BIT(OCTOSPIM->CR, OCTOSPIM_CR_MUXEN);
+ }
+ else
+ {
+ CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].ClkPort-1U)], OCTOSPIM_PCR_CLKEN);
+ CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].DQSPort-1U)], OCTOSPIM_PCR_DQSEN);
+ CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].NCSPort-1U)], OCTOSPIM_PCR_NCSEN);
+ CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOLowPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOLEN);
+ CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOHighPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOHEN);
+ }
+ }
+
+ /******************** Activation of new configuration *********************/
+ MODIFY_REG(OCTOSPIM->PCR[(cfg->NCSPort-1U)], (OCTOSPIM_PCR_NCSEN | OCTOSPIM_PCR_NCSSRC), (OCTOSPIM_PCR_NCSEN | (instance << OCTOSPIM_PCR_NCSSRC_Pos)));
+
+ if ((cfg->Req2AckTime - 1U) > ((OCTOSPIM->CR & OCTOSPIM_CR_REQ2ACK_TIME) >> OCTOSPIM_CR_REQ2ACK_TIME_Pos))
+ {
+ MODIFY_REG(OCTOSPIM->CR, OCTOSPIM_CR_REQ2ACK_TIME, ((cfg->Req2AckTime - 1U) << OCTOSPIM_CR_REQ2ACK_TIME_Pos));
+ }
+
+ if ((OCTOSPIM->CR & OCTOSPIM_CR_MUXEN) != 0U)
+ {
+ MODIFY_REG(OCTOSPIM->PCR[(cfg->ClkPort-1U)], (OCTOSPIM_PCR_CLKEN | OCTOSPIM_PCR_CLKSRC), OCTOSPIM_PCR_CLKEN);
+ MODIFY_REG(OCTOSPIM->PCR[(cfg->DQSPort-1U)], (OCTOSPIM_PCR_DQSEN | OCTOSPIM_PCR_DQSSRC), OCTOSPIM_PCR_DQSEN);
+
+ if ((cfg->IOLowPort & OCTOSPIM_PCR_IOLEN) != 0U)
+ {
+ MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC), OCTOSPIM_PCR_IOLEN);
+ }
+ else
+ {
+ MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC), OCTOSPIM_PCR_IOHEN);
+ }
+
+ if ((cfg->IOHighPort & OCTOSPIM_PCR_IOLEN) != 0U)
+ {
+ MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC), (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC_0));
+ }
+ else
+ {
+ MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC), (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC_0));
+ }
+ }
+ else
+ {
+ MODIFY_REG(OCTOSPIM->PCR[(cfg->ClkPort-1U)], (OCTOSPIM_PCR_CLKEN | OCTOSPIM_PCR_CLKSRC), (OCTOSPIM_PCR_CLKEN | (instance << OCTOSPIM_PCR_CLKSRC_Pos)));
+ MODIFY_REG(OCTOSPIM->PCR[(cfg->DQSPort-1U)], (OCTOSPIM_PCR_DQSEN | OCTOSPIM_PCR_DQSSRC), (OCTOSPIM_PCR_DQSEN | (instance << OCTOSPIM_PCR_DQSSRC_Pos)));
+
+ if ((cfg->IOLowPort & OCTOSPIM_PCR_IOLEN) != 0U)
+ {
+ MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC),
+ (OCTOSPIM_PCR_IOLEN | (instance << (OCTOSPIM_PCR_IOLSRC_Pos+1U))));
+ }
+ else
+ {
+ MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC),
+ (OCTOSPIM_PCR_IOHEN | (instance << (OCTOSPIM_PCR_IOHSRC_Pos+1U))));
+ }
+
+ if ((cfg->IOHighPort & OCTOSPIM_PCR_IOLEN) != 0U)
+ {
+ MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC),
+ (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC_0 | (instance << (OCTOSPIM_PCR_IOLSRC_Pos+1U))));
+ }
+ else
+ {
+ MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC),
+ (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC_0 | (instance << (OCTOSPIM_PCR_IOHSRC_Pos+1U))));
+ }
+ }
+
+ /******* Re-enable both OctoSPI after configure OctoSPI IO Manager ********/
+ if ((ospi_enabled & 0x1U) != 0U)
+ {
+ SET_BIT(OCTOSPI1->CR, OCTOSPI_CR_EN);
+ }
+ if ((ospi_enabled & 0x2U) != 0U)
+ {
+ SET_BIT(OCTOSPI2->CR, OCTOSPI_CR_EN);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ @cond 0
+ */
+/**
+ * @brief DMA OSPI process complete callback.
+ * @param hdma : DMA handle
+ * @retval None
+ */
+static void OSPI_DMACplt(MDMA_HandleTypeDef *hmdma)
+{
+ OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hmdma->Parent);
+ hospi->XferCount = 0;
+
+ /* Disable the DMA transfer on the OctoSPI side */
+ CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
+
+ /* Disable the DMA channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Enable the OSPI transfer complete Interrupt */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC);
+}
+
+/**
+ * @brief DMA OSPI communication error callback.
+ * @param hdma : DMA handle
+ * @retval None
+ */
+static void OSPI_DMAError(MDMA_HandleTypeDef *hmdma)
+{
+ OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hmdma->Parent);
+ hospi->XferCount = 0;
+ hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
+
+ /* Disable the DMA transfer on the OctoSPI side */
+ CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
+
+ /* Abort the OctoSPI */
+ if (HAL_OSPI_Abort_IT(hospi) != HAL_OK)
+ {
+ /* Disable the interrupts */
+ __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
+
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+
+ /* Error callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->ErrorCallback(hospi);
+#else
+ HAL_OSPI_ErrorCallback(hospi);
+#endif
+ }
+}
+
+/**
+ * @brief DMA OSPI abort complete callback.
+ * @param hdma : DMA handle
+ * @retval None
+ */
+static void OSPI_DMAAbortCplt(MDMA_HandleTypeDef *hmdma)
+{
+ OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hmdma->Parent);
+ hospi->XferCount = 0;
+
+ /* Check the state */
+ if (hospi->State == HAL_OSPI_STATE_ABORT)
+ {
+ /* DMA abort called by OctoSPI abort */
+ if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET)
+ {
+ /* Clear transfer complete flag */
+ __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
+
+ /* Enable the transfer complete interrupts */
+ __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC);
+
+ /* Perform an abort of the OctoSPI */
+ SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT);
+ }
+ else
+ {
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+
+ /* Abort callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->AbortCpltCallback(hospi);
+#else
+ HAL_OSPI_AbortCpltCallback(hospi);
+#endif
+ }
+ }
+ else
+ {
+ /* DMA abort called due to a transfer error interrupt */
+ /* Update state */
+ hospi->State = HAL_OSPI_STATE_READY;
+
+ /* Error callback */
+#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
+ hospi->ErrorCallback(hospi);
+#else
+ HAL_OSPI_ErrorCallback(hospi);
+#endif
+ }
+}
+
+/**
+ * @brief Wait for a flag state until timeout.
+ * @param hospi : OSPI handle
+ * @param Flag : Flag checked
+ * @param State : Value of the flag expected
+ * @param Timeout : Duration of the timeout
+ * @param Tickstart : Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef OSPI_WaitFlagStateUntilTimeout(OSPI_HandleTypeDef *hospi, uint32_t Flag,
+ FlagStatus State, uint32_t Tickstart, uint32_t Timeout)
+{
+ /* Wait until flag is in expected state */
+ while((__HAL_OSPI_GET_FLAG(hospi, Flag)) != State)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hospi->State = HAL_OSPI_STATE_ERROR;
+ hospi->ErrorCode |= HAL_OSPI_ERROR_TIMEOUT;
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the registers for the regular command mode.
+ * @param hospi : OSPI handle
+ * @param cmd : structure that contains the command configuration information
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef OSPI_ConfigCmd(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ __IO uint32_t *ccr_reg, *tcr_reg, *ir_reg, *abr_reg;
+
+ /* Re-initialize the value of the functional mode */
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, 0U);
+
+ /* Configure the flash ID */
+ if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE)
+ {
+ MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FSEL, cmd->FlashId);
+ }
+
+ if (cmd->OperationType == HAL_OSPI_OPTYPE_WRITE_CFG)
+ {
+ ccr_reg = &(hospi->Instance->WCCR);
+ tcr_reg = &(hospi->Instance->WTCR);
+ ir_reg = &(hospi->Instance->WIR);
+ abr_reg = &(hospi->Instance->WABR);
+ }
+ else if (cmd->OperationType == HAL_OSPI_OPTYPE_WRAP_CFG)
+ {
+ ccr_reg = &(hospi->Instance->WPCCR);
+ tcr_reg = &(hospi->Instance->WPTCR);
+ ir_reg = &(hospi->Instance->WPIR);
+ abr_reg = &(hospi->Instance->WPABR);
+ }
+ else
+ {
+ ccr_reg = &(hospi->Instance->CCR);
+ tcr_reg = &(hospi->Instance->TCR);
+ ir_reg = &(hospi->Instance->IR);
+ abr_reg = &(hospi->Instance->ABR);
+ }
+
+ /* Configure the CCR register with DQS and SIOO modes */
+ *ccr_reg = (cmd->DQSMode | cmd->SIOOMode);
+
+ if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE)
+ {
+ /* Configure the ABR register with alternate bytes value */
+ *abr_reg = cmd->AlternateBytes;
+
+ /* Configure the CCR register with alternate bytes communication parameters */
+ MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ABMODE | OCTOSPI_CCR_ABDTR | OCTOSPI_CCR_ABSIZE),
+ (cmd->AlternateBytesMode | cmd->AlternateBytesDtrMode | cmd->AlternateBytesSize));
+ }
+
+ /* Configure the TCR register with the number of dummy cycles */
+ MODIFY_REG((*tcr_reg), OCTOSPI_TCR_DCYC, cmd->DummyCycles);
+
+ if (cmd->DataMode != HAL_OSPI_DATA_NONE)
+ {
+ if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG)
+ {
+ /* Configure the DLR register with the number of data */
+ hospi->Instance->DLR = (cmd->NbData - 1U);
+ }
+ }
+
+ if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE)
+ {
+ if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
+ {
+ if (cmd->DataMode != HAL_OSPI_DATA_NONE)
+ {
+ /* ---- Command with instruction, address and data ---- */
+
+ /* Configure the CCR register with all communication parameters */
+ MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE |
+ OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE |
+ OCTOSPI_CCR_DMODE | OCTOSPI_CCR_DDTR),
+ (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize |
+ cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize |
+ cmd->DataMode | cmd->DataDtrMode));
+ }
+ else
+ {
+ /* ---- Command with instruction and address ---- */
+
+ /* Configure the CCR register with all communication parameters */
+ MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE |
+ OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE),
+ (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize |
+ cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize));
+
+ /* The DHQC bit is linked with DDTR bit which should be activated */
+ if ((hospi->Init.DelayHoldQuarterCycle == HAL_OSPI_DHQC_ENABLE) &&
+ (cmd->InstructionDtrMode == HAL_OSPI_INSTRUCTION_DTR_ENABLE))
+ {
+ MODIFY_REG((*ccr_reg), OCTOSPI_CCR_DDTR, HAL_OSPI_DATA_DTR_ENABLE);
+ }
+ }
+
+ /* Configure the IR register with the instruction value */
+ *ir_reg = cmd->Instruction;
+
+ /* Configure the AR register with the address value */
+ hospi->Instance->AR = cmd->Address;
+ }
+ else
+ {
+ if (cmd->DataMode != HAL_OSPI_DATA_NONE)
+ {
+ /* ---- Command with instruction and data ---- */
+
+ /* Configure the CCR register with all communication parameters */
+ MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE |
+ OCTOSPI_CCR_DMODE | OCTOSPI_CCR_DDTR),
+ (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize |
+ cmd->DataMode | cmd->DataDtrMode));
+ }
+ else
+ {
+ /* ---- Command with only instruction ---- */
+
+ /* Configure the CCR register with all communication parameters */
+ MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE),
+ (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize));
+
+ /* The DHQC bit is linked with DDTR bit which should be activated */
+ if ((hospi->Init.DelayHoldQuarterCycle == HAL_OSPI_DHQC_ENABLE) &&
+ (cmd->InstructionDtrMode == HAL_OSPI_INSTRUCTION_DTR_ENABLE))
+ {
+ MODIFY_REG((*ccr_reg), OCTOSPI_CCR_DDTR, HAL_OSPI_DATA_DTR_ENABLE);
+ }
+ }
+
+ /* Configure the IR register with the instruction value */
+ *ir_reg = cmd->Instruction;
+
+ }
+ }
+ else
+ {
+ if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
+ {
+ if (cmd->DataMode != HAL_OSPI_DATA_NONE)
+ {
+ /* ---- Command with address and data ---- */
+
+ /* Configure the CCR register with all communication parameters */
+ MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE |
+ OCTOSPI_CCR_DMODE | OCTOSPI_CCR_DDTR),
+ (cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize |
+ cmd->DataMode | cmd->DataDtrMode));
+ }
+ else
+ {
+ /* ---- Command with only address ---- */
+
+ /* Configure the CCR register with all communication parameters */
+ MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE),
+ (cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize));
+ }
+
+ /* Configure the AR register with the instruction value */
+ hospi->Instance->AR = cmd->Address;
+ }
+ else
+ {
+ /* ---- Invalid command configuration (no instruction, no address) ---- */
+ status = HAL_ERROR;
+ hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Get the current IOM configuration for an OctoSPI instance.
+ * @param instance_nb : number of the instance
+ * @param cfg : configuration of the IO Manager for the instance
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef OSPIM_GetConfig(uint8_t instance_nb, OSPIM_CfgTypeDef *cfg)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t reg, value = 0U;
+ uint32_t index;
+
+ if ((instance_nb == 0U) || (instance_nb > OSPI_NB_INSTANCE) || (cfg == NULL))
+ {
+ /* Invalid parameter -> error returned */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Initialize the structure */
+ cfg->ClkPort = 0U;
+ cfg->DQSPort = 0U;
+ cfg->NCSPort = 0U;
+ cfg->IOLowPort = 0U;
+ cfg->IOHighPort = 0U;
+
+ if (instance_nb == 2U)
+ {
+ if ((OCTOSPIM->CR & OCTOSPIM_CR_MUXEN) == 0U)
+ {
+ value = (OCTOSPIM_PCR_CLKSRC | OCTOSPIM_PCR_DQSSRC | OCTOSPIM_PCR_NCSSRC | OCTOSPIM_PCR_IOLSRC_1 | OCTOSPIM_PCR_IOHSRC_1);
+ }
+ else
+ {
+ value = OCTOSPIM_PCR_NCSSRC;
+ }
+ }
+
+ /* Get the information about the instance */
+ for (index = 0U; index < OSPI_IOM_NB_PORTS; index ++)
+ {
+ reg = OCTOSPIM->PCR[index];
+
+ if ((reg & OCTOSPIM_PCR_CLKEN) != 0U)
+ {
+ /* The clock is enabled on this port */
+ if ((reg & OCTOSPIM_PCR_CLKSRC) == (value & OCTOSPIM_PCR_CLKSRC))
+ {
+ /* The clock correspond to the instance passed as parameter */
+ cfg->ClkPort = index+1U;
+ }
+ }
+
+ if ((reg & OCTOSPIM_PCR_DQSEN) != 0U)
+ {
+ /* The DQS is enabled on this port */
+ if ((reg & OCTOSPIM_PCR_DQSSRC) == (value & OCTOSPIM_PCR_DQSSRC))
+ {
+ /* The DQS correspond to the instance passed as parameter */
+ cfg->DQSPort = index+1U;
+ }
+ }
+
+ if ((reg & OCTOSPIM_PCR_NCSEN) != 0U)
+ {
+ /* The nCS is enabled on this port */
+ if ((reg & OCTOSPIM_PCR_NCSSRC) == (value & OCTOSPIM_PCR_NCSSRC))
+ {
+ /* The nCS correspond to the instance passed as parameter */
+ cfg->NCSPort = index+1U;
+ }
+ }
+
+ if ((reg & OCTOSPIM_PCR_IOLEN) != 0U)
+ {
+ /* The IO Low is enabled on this port */
+ if ((reg & OCTOSPIM_PCR_IOLSRC_1) == (value & OCTOSPIM_PCR_IOLSRC_1))
+ {
+ /* The IO Low correspond to the instance passed as parameter */
+ if ((reg & OCTOSPIM_PCR_IOLSRC_0) == 0U)
+ {
+ cfg->IOLowPort = (OCTOSPIM_PCR_IOLEN | (index+1U));
+ }
+ else
+ {
+ cfg->IOLowPort = (OCTOSPIM_PCR_IOHEN | (index+1U));
+ }
+ }
+ }
+
+ if ((reg & OCTOSPIM_PCR_IOHEN) != 0U)
+ {
+ /* The IO High is enabled on this port */
+ if ((reg & OCTOSPIM_PCR_IOHSRC_1) == (value & OCTOSPIM_PCR_IOHSRC_1))
+ {
+ /* The IO High correspond to the instance passed as parameter */
+ if ((reg & OCTOSPIM_PCR_IOHSRC_0) == 0U)
+ {
+ cfg->IOHighPort = (OCTOSPIM_PCR_IOLEN | (index+1U));
+ }
+ else
+ {
+ cfg->IOHighPort = (OCTOSPIM_PCR_IOHEN | (index+1U));
+ }
+ }
+ }
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ @endcond
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_OSPI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* OCTOSPI || OCTOSPI1 || OCTOSPI2 */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_otfdec.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_otfdec.c
new file mode 100644
index 0000000000..e4ace0de90
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_otfdec.c
@@ -0,0 +1,998 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_otfdec.c
+ * @author MCD Application Team
+ * @brief OTFDEC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the On-The-Fly Decryption (OTFDEC) peripheral:
+ * + Initialization and de-initialization functions
+ * + Region setting/enable functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The OTFDEC HAL driver can be used as follows:
+
+ (#) Declare an OTFDEC_HandleTypeDef handle structure (eg. OTFDEC_HandleTypeDef hotfdec).
+
+ (#) Initialize the OTFDEC low level resources by implementing the HAL_OTFDEC_MspInit() API:
+ (++) Enable the OTFDEC interface clock.
+ (++) NVIC configuration if interrupts are used
+ (+++) Configure the OTFDEC interrupt priority.
+ (+++) Enable the NVIC OTFDEC IRQ handle.
+
+ (#) Initialize the OTFDEC peripheral by calling the HAL_OTFDEC_Init() API.
+
+ (#) For each region,
+
+ (++) Configure the region deciphering mode by calling the HAL_OTFDEC_RegionSetMode() API.
+
+ (++) Write the region Key by calling the HAL_OTFDEC_RegionSetKey() API. If desired,
+ read the key CRC by calling HAL_OTFDEC_RegionGetKeyCRC() API and compare the
+ result with the theoretically expected CRC.
+
+ (++) Initialize the OTFDEC region config structure with the Nonce, protected
+ region start and end addresses and firmware version, and wrap-up the region
+ configuration by calling HAL_OTFDEC_RegionConfig() API.
+
+ (#) At this point, the OTFDEC region configuration is done and the deciphering
+ is enabled. The region can be deciphered on the fly after having made sure
+ the OctoSPI is configured in memory-mapped mode.
+
+ [..]
+ (@) Warning: the OTFDEC deciphering is based on a different endianness compared
+ to the AES-CTR as implemented in the AES peripheral. E.g., if the OTFEC
+ resorts to the Key (B0, B1, B2, B3) where Bi are 32-bit longwords and B0
+ is the Least Significant Word, the AES has to be configured with the Key
+ (B3, B2, B1, B0) to report the same result (with the same swapping applied
+ to the Initialization Vector).
+
+ [..]
+
+ *** Callback registration ***
+ =============================================
+ [..]
+
+ The compilation flag USE_HAL_OTFDEC_REGISTER_CALLBACKS, when set to 1,
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions @ref HAL_OTFDEC_RegisterCallback()
+ to register an interrupt callback.
+ [..]
+
+ Function @ref HAL_OTFDEC_RegisterCallback() allows to register following callbacks:
+ (+) ErrorCallback : OTFDEC error callback
+ (+) MspInitCallback : OTFDEC Msp Init callback
+ (+) MspDeInitCallback : OTFDEC Msp DeInit callback
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+ [..]
+
+ Use function @ref HAL_OTFDEC_UnRegisterCallback to reset a callback to the default
+ weak function.
+ [..]
+
+ @ref HAL_OTFDEC_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) ErrorCallback : OTFDEC error callback
+ (+) MspInitCallback : OTFDEC Msp Init callback
+ (+) MspDeInitCallback : OTFDEC Msp DeInit callback
+ [..]
+
+ By default, after the @ref HAL_OTFDEC_Init() and when the state is @ref HAL_OTFDEC_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ example @ref HAL_OTFDEC_ErrorCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the @ref HAL_OTFDEC_Init()/ @ref HAL_OTFDEC_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ [..]
+
+ If MspInit or MspDeInit are not null, the @ref HAL_OTFDEC_Init()/ @ref HAL_OTFDEC_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+ [..]
+
+ Callbacks can be registered/unregistered in @ref HAL_OTFDEC_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in @ref HAL_OTFDEC_STATE_READY or @ref HAL_OTFDEC_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 @ref HAL_OTFDEC_RegisterCallback() before calling @ref HAL_OTFDEC_DeInit()
+ or @ref HAL_OTFDEC_Init() function.
+ [..]
+
+ When the compilation flag USE_HAL_OTFDEC_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2018 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup OTFDEC OTFDEC
+ * @brief OTFDEC HAL module driver.
+ * @{
+ */
+
+
+#ifdef HAL_OTFDEC_MODULE_ENABLED
+
+#if defined(OTFDEC1)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+
+
+ /* Exported functions --------------------------------------------------------*/
+/** @addtogroup OTFDEC_Exported_Functions
+ * @{
+ */
+
+/** @defgroup OTFDEC_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the OTFDEC peripheral and create the associated handle.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OTFDEC_Init(OTFDEC_HandleTypeDef *hotfdec)
+{
+ /* Check the OTFDEC handle allocation */
+ if(hotfdec == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+
+ if(hotfdec->State == HAL_OTFDEC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ __HAL_UNLOCK(hotfdec);
+
+#if (USE_HAL_OTFDEC_REGISTER_CALLBACKS == 1)
+ /* Init the OTFDEC Callback settings */
+ hotfdec->ErrorCallback = HAL_OTFDEC_ErrorCallback; /* Legacy weak callback */
+
+ if (hotfdec->MspInitCallback == NULL)
+ {
+ hotfdec->MspInitCallback = HAL_OTFDEC_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware */
+ hotfdec->MspInitCallback(hotfdec);
+#else
+ /* Init the low level hardware */
+ HAL_OTFDEC_MspInit(hotfdec);
+#endif /* USE_HAL_OTFDEC_REGISTER_CALLBACKS */
+ }
+
+ /* Change the OTFDEC state */
+ hotfdec->State = HAL_OTFDEC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the OTFDEC peripheral.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OTFDEC_DeInit(OTFDEC_HandleTypeDef *hotfdec)
+{
+ /* Check the OTFDEC handle allocation */
+ if(hotfdec == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+
+ /* Change the OTFDEC state */
+ hotfdec->State = HAL_OTFDEC_STATE_BUSY;
+
+#if (USE_HAL_OTFDEC_REGISTER_CALLBACKS == 1)
+ if (hotfdec->MspDeInitCallback == NULL)
+ {
+ hotfdec->MspDeInitCallback = HAL_OTFDEC_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: CLOCK, NVIC */
+ hotfdec->MspDeInitCallback(hotfdec);
+#else
+ /* DeInit the low level hardware: CLOCK, NVIC */
+ HAL_OTFDEC_MspDeInit(hotfdec);
+#endif /* USE_HAL_OTFDEC_REGISTER_CALLBACKS */
+
+ /* Change the OTFDEC state */
+ hotfdec->State = HAL_OTFDEC_STATE_RESET;
+
+ /* Reset OTFDEC error status */
+ hotfdec->ErrorCode = HAL_OTFDEC_ERROR_NONE;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hotfdec);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the OTFDEC MSP.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @retval None
+ */
+__weak void HAL_OTFDEC_MspInit(OTFDEC_HandleTypeDef *hotfdec)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hotfdec);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ the HAL_OTFDEC_MspInit can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief DeInitialize OTFDEC MSP.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @retval None
+ */
+__weak void HAL_OTFDEC_MspDeInit(OTFDEC_HandleTypeDef *hotfdec)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hotfdec);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ the HAL_OTFDEC_MspDeInit can be implemented in the user file.
+ */
+}
+
+#if (USE_HAL_OTFDEC_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User OTFDEC Callback
+ * To be used instead of the weak predefined callback
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_OTFDEC_ERROR_CB_ID OTFDEC error callback ID
+ * @arg @ref HAL_OTFDEC_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_OTFDEC_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OTFDEC_RegisterCallback(OTFDEC_HandleTypeDef *hotfdec, HAL_OTFDEC_CallbackIDTypeDef CallbackID, pOTFDEC_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hotfdec->ErrorCode |= HAL_OTFDEC_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ if (hotfdec->State == HAL_OTFDEC_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_OTFDEC_ERROR_CB_ID :
+ hotfdec->ErrorCallback = pCallback;
+ break;
+
+ case HAL_OTFDEC_MSPINIT_CB_ID :
+ hotfdec->MspInitCallback = pCallback;
+ break;
+
+ case HAL_OTFDEC_MSPDEINIT_CB_ID :
+ hotfdec->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hotfdec->ErrorCode |= HAL_OTFDEC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_OTFDEC_STATE_RESET == hotfdec->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_OTFDEC_MSPINIT_CB_ID :
+ hotfdec->MspInitCallback = pCallback;
+ break;
+
+ case HAL_OTFDEC_MSPDEINIT_CB_ID :
+ hotfdec->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hotfdec->ErrorCode |= HAL_OTFDEC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hotfdec->ErrorCode |= HAL_OTFDEC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a OTFDEC Callback
+ * OTFDEC callback is redirected to the weak predefined callback
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_OTFDEC_ERROR_CB_ID OTFDEC error callback ID
+ * @arg @ref HAL_OTFDEC_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_OTFDEC_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_OTFDEC_UnRegisterCallback(OTFDEC_HandleTypeDef *hotfdec, HAL_OTFDEC_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hotfdec->State == HAL_OTFDEC_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_OTFDEC_ERROR_CB_ID :
+ hotfdec->ErrorCallback = HAL_OTFDEC_ErrorCallback;
+ break;
+
+ case HAL_OTFDEC_MSPINIT_CB_ID :
+ hotfdec->MspInitCallback = HAL_OTFDEC_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_OTFDEC_MSPDEINIT_CB_ID :
+ hotfdec->MspDeInitCallback = HAL_OTFDEC_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hotfdec->ErrorCode |= HAL_OTFDEC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_OTFDEC_STATE_RESET == hotfdec->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_OTFDEC_MSPINIT_CB_ID :
+ hotfdec->MspInitCallback = HAL_OTFDEC_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_OTFDEC_MSPDEINIT_CB_ID :
+ hotfdec->MspDeInitCallback = HAL_OTFDEC_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hotfdec->ErrorCode |= HAL_OTFDEC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hotfdec->ErrorCode |= HAL_OTFDEC_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+#endif /* USE_HAL_OTFDEC_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup OTFDEC_Exported_Functions_Group2 OTFDEC IRQ handler management
+ * @brief OTFDEC IRQ handler.
+ *
+@verbatim
+ ==============================================================================
+ ##### OTFDEC IRQ handler management #####
+ ==============================================================================
+[..] This section provides OTFDEC IRQ handler function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Handle OTFDEC interrupt request.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @retval None
+ */
+void HAL_OTFDEC_IRQHandler(OTFDEC_HandleTypeDef *hotfdec)
+{
+ uint32_t isr_reg;
+
+ isr_reg = READ_REG(hotfdec->Instance->ISR);
+ if ((isr_reg & OTFDEC_ISR_SEIF) == OTFDEC_ISR_SEIF)
+ {
+ SET_BIT( hotfdec->Instance->ICR, OTFDEC_ICR_SEIF );
+ hotfdec->ErrorCode |= HAL_OTFDEC_SECURITY_ERROR;
+ }
+ if ((isr_reg & OTFDEC_ISR_XONEIF) == OTFDEC_ISR_XONEIF)
+ {
+ SET_BIT( hotfdec->Instance->ICR, OTFDEC_ICR_XONEIF );
+ hotfdec->ErrorCode |= HAL_OTFDEC_EXECUTE_ERROR;
+ }
+ if ((isr_reg & OTFDEC_ISR_KEIF) == OTFDEC_ISR_KEIF)
+ {
+ SET_BIT( hotfdec->Instance->ICR, OTFDEC_ICR_KEIF );
+ hotfdec->ErrorCode |= HAL_OTFDEC_KEY_ERROR;
+ }
+
+#if (USE_HAL_OTFDEC_REGISTER_CALLBACKS == 1)
+ hotfdec->ErrorCallback(hotfdec);
+#else
+ HAL_OTFDEC_ErrorCallback(hotfdec);
+#endif /* USE_HAL_OTFDEC_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief OTFDEC error callback.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @retval None
+ */
+__weak void HAL_OTFDEC_ErrorCallback(OTFDEC_HandleTypeDef *hotfdec)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hotfdec);
+
+ /* NOTE : This function should not be modified; when the callback is needed,
+ the HAL_OTFDEC_ErrorCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+
+
+
+/** @defgroup OTFDEC_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Peripheral control functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to configure the OTFDEC peripheral
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Lock region keys.
+ * @note Writes to this region KEYRx registers are ignored until next OTFDEC reset.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param RegionIndex index of region the keys of which are locked
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_OTFDEC_RegionKeyLock(OTFDEC_HandleTypeDef *hotfdec, uint32_t RegionIndex)
+{
+ OTFDEC_Region_TypeDef * region;
+ uint32_t address;
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+ assert_param(IS_OTFDEC_REGIONINDEX(RegionIndex));
+
+ /* Take Lock */
+ __HAL_LOCK(hotfdec);
+
+ address = (uint32_t)(hotfdec->Instance) + 0x20U + (0x30U * RegionIndex);
+ region = (OTFDEC_Region_TypeDef *)address;
+
+ SET_BIT( region->REG_CONFIGR, OTFDEC_REG_CONFIGR_KEYLOCK );
+
+ /* Release Lock */
+ __HAL_UNLOCK(hotfdec);
+
+ /* Status is okay */
+ return HAL_OK;
+}
+
+/**
+ * @brief Set region keys.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param RegionIndex index of region the keys of which are set
+ * @param pKey pointer at set of keys
+ * @note The API reads the key CRC computed by the peripheral and compares it with thzt
+ * theoretically expected. An error is reported if they are different.
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_OTFDEC_RegionSetKey(OTFDEC_HandleTypeDef *hotfdec, uint32_t RegionIndex, uint32_t *pKey)
+{
+ OTFDEC_Region_TypeDef * region;
+ uint32_t address;
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+ assert_param(IS_OTFDEC_REGIONINDEX(RegionIndex));
+
+ if (pKey == NULL)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Take Lock */
+ __HAL_LOCK(hotfdec);
+
+ address = (uint32_t)(hotfdec->Instance) + 0x20U + (0x30U * RegionIndex);
+ region = (OTFDEC_Region_TypeDef *)address;
+
+ /* Set Key */
+ WRITE_REG( region->REG_KEYR0, pKey[0]);
+
+ __DSB();
+ __ISB();
+
+ WRITE_REG( region->REG_KEYR1, pKey[1]);
+
+ __DSB();
+ __ISB();
+
+ WRITE_REG( region->REG_KEYR2, pKey[2]);
+
+ __DSB();
+ __ISB();
+
+ WRITE_REG( region->REG_KEYR3, pKey[3]);
+
+ /* Compute theoretically expected CRC and compare it with that reported by the peripheral */
+ if (HAL_OTFDEC_KeyCRCComputation(pKey) != HAL_OTFDEC_RegionGetKeyCRC(hotfdec, RegionIndex))
+ {
+ /* Release Lock */
+ __HAL_UNLOCK(hotfdec);
+
+ /* Status is okay */
+ return HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hotfdec);
+
+ /* Status is okay */
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Set region mode.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param RegionIndex index of region the mode of which is set
+ * @param mode This parameter can be only:
+ * @arg @ref OTFDEC_REG_MODE_INSTRUCTION_ACCESSES_ONLY Only instruction accesses are decrypted
+ * @arg @ref OTFDEC_REG_MODE_DATA_ACCESSES_ONLY Only data accesses are decrypted
+ * @arg @ref OTFDEC_REG_MODE_INSTRUCTION_OR_DATA_ACCESSES All read accesses are decrypted (instruction or data)
+ * @arg @ref OTFDEC_REG_MODE_INSTRUCTION_ACCESSES_ONLY_WITH_CIPHER Only instruction accesses are decrypted with proprietary cipher activated
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_OTFDEC_RegionSetMode(OTFDEC_HandleTypeDef *hotfdec, uint32_t RegionIndex, uint32_t mode)
+{
+ OTFDEC_Region_TypeDef * region;
+ uint32_t address;
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+ assert_param(IS_OTFDEC_REGIONINDEX(RegionIndex));
+ assert_param(IS_OTFDEC_REGION_OPERATING_MODE(mode));
+
+ /* Take Lock */
+ __HAL_LOCK(hotfdec);
+
+ address = (uint32_t)(hotfdec->Instance) + 0x20U + (0x30U * RegionIndex);
+ region = (OTFDEC_Region_TypeDef *)address;
+
+ /* Set mode */
+ MODIFY_REG(region->REG_CONFIGR, OTFDEC_REG_CONFIGR_MODE, mode);
+
+ /* Release Lock */
+ __HAL_UNLOCK(hotfdec);
+
+ /* Status is okay */
+ return HAL_OK;
+}
+
+/**
+ * @brief Set region configuration.
+ * @note Region deciphering is enabled at the end of this function
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param RegionIndex index of region that is configured
+ * @param Config pointer on structure containing the region configuration parameters
+ * @param lock configuration lock enable or disable parameter
+ * This parameter can be one of the following values:
+ * @arg @ref OTFDEC_REG_CONFIGR_LOCK_DISABLE OTFDEC region configuration is not locked
+ * @arg @ref OTFDEC_REG_CONFIGR_LOCK_ENABLE OTFDEC region configuration is locked
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_OTFDEC_RegionConfig(OTFDEC_HandleTypeDef *hotfdec, uint32_t RegionIndex, OTFDEC_RegionConfigTypeDef *Config, uint32_t lock)
+{
+ OTFDEC_Region_TypeDef * region;
+ uint32_t address;
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+ assert_param(IS_OTFDEC_REGIONINDEX(RegionIndex));
+ assert_param(IS_OTFDEC_REGION_CONFIG_LOCK(lock));
+
+ if (Config == NULL)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+
+ /* Take Lock */
+ __HAL_LOCK(hotfdec);
+
+ address = (uint32_t)(hotfdec->Instance) + 0x20U + (0x30U * RegionIndex);
+ region = (OTFDEC_Region_TypeDef *)address;
+
+ /* Set Nonce */
+ WRITE_REG( region->REG_NONCER0, Config->Nonce[0]);
+
+ WRITE_REG( region->REG_NONCER1, Config->Nonce[1]);
+
+ /* Write region protected area start and end addresses */
+ WRITE_REG( region->REG_START_ADDR, Config->StartAddress);
+
+ WRITE_REG( region->REG_END_ADDR, Config->EndAddress);
+
+ /* Write Version */
+ MODIFY_REG( region->REG_CONFIGR, OTFDEC_REG_CONFIGR_VERSION, (uint32_t)(Config->Version) << OTFDEC_REG_CONFIGR_VERSION_Pos );
+
+ /* Enable region deciphering or enciphering (depending of OTFDEC_CR ENC bit setting) */
+ SET_BIT( region->REG_CONFIGR, OTFDEC_REG_CONFIGR_REG_ENABLE);
+
+ /* Lock the region configuration according to lock parameter value */
+ if (lock == OTFDEC_REG_CONFIGR_LOCK_ENABLE)
+ {
+ SET_BIT( region->REG_CONFIGR, OTFDEC_REG_CONFIGR_LOCK_ENABLE);
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hotfdec);
+
+ /* Status is okay */
+ return HAL_OK;
+ }
+}
+
+
+/**
+ * @brief Compute Key CRC
+ * @param pKey pointer at set of keys
+ * @retval CRC value
+ */
+uint32_t HAL_OTFDEC_KeyCRCComputation(uint32_t *pKey)
+{
+ uint8_t crc7_poly = 0x7;
+ uint32_t key_strobe[4] = {0xAA55AA55U, 0x3U, 0x18U, 0xC0U};
+ uint8_t i;
+ uint8_t crc = 0;
+ uint32_t j, keyval, k;
+ uint32_t * temp = pKey;
+
+ for (j = 0U; j < 4U; j++)
+ {
+ keyval = *temp;
+ temp++;
+ if (j == 0U)
+ {
+ keyval ^= key_strobe[0];
+ }
+ else
+ {
+ keyval ^= (key_strobe[j] << 24) | ((uint32_t)crc << 16) | (key_strobe[j] << 8) | crc;
+ }
+
+ crc = 0;
+ for (i = 0; i < (uint8_t)32; i++)
+ {
+ k = ((((uint32_t)crc >> 7) ^ ((keyval >> ((uint8_t)31-i))&((uint8_t)0xF)))) & 1U;
+ crc <<= 1;
+ if (k != 0U)
+ {
+ crc ^= crc7_poly;
+ }
+ }
+
+ crc^=(uint8_t)0x55;
+ }
+
+ return (uint32_t) crc;
+}
+
+
+/**
+ * @brief Enable region deciphering.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param RegionIndex index of region the deciphering is enabled
+ * @note An error is reported when the configuration is locked.
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_OTFDEC_RegionEnable(OTFDEC_HandleTypeDef *hotfdec, uint32_t RegionIndex)
+{
+ OTFDEC_Region_TypeDef * region;
+ uint32_t address;
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+ assert_param(IS_OTFDEC_REGIONINDEX(RegionIndex));
+
+ /* Take Lock */
+ __HAL_LOCK(hotfdec);
+
+ address = (uint32_t)(hotfdec->Instance) + 0x20U + (0x30U * RegionIndex);
+ region = (OTFDEC_Region_TypeDef *)address;
+
+ if (READ_BIT( region->REG_CONFIGR, OTFDEC_REG_CONFIGR_LOCK_ENABLE) == OTFDEC_REG_CONFIGR_LOCK_ENABLE)
+ {
+ /* Configuration is locked, REG_EN bit can't be modified */
+ __HAL_UNLOCK(hotfdec);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable region processing */
+ SET_BIT( region->REG_CONFIGR, OTFDEC_REG_CONFIGR_REG_ENABLE);
+
+ /* Release Lock */
+ __HAL_UNLOCK(hotfdec);
+
+ /* Status is okay */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable region deciphering.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param RegionIndex index of region the deciphering is disabled
+ * @note An error is reported when the configuration is locked.
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_OTFDEC_RegionDisable(OTFDEC_HandleTypeDef *hotfdec, uint32_t RegionIndex)
+{
+ OTFDEC_Region_TypeDef * region;
+ uint32_t address;
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+ assert_param(IS_OTFDEC_REGIONINDEX(RegionIndex));
+
+ /* Take Lock */
+ __HAL_LOCK(hotfdec);
+
+ address = (uint32_t)(hotfdec->Instance) + 0x20U + (0x30U * RegionIndex);
+ region = (OTFDEC_Region_TypeDef *)address;
+
+ if (READ_BIT( region->REG_CONFIGR, OTFDEC_REG_CONFIGR_LOCK_ENABLE) == OTFDEC_REG_CONFIGR_LOCK_ENABLE)
+ {
+ /* Configuration is locked, REG_EN bit can't be modified */
+ __HAL_UNLOCK(hotfdec);
+
+ return HAL_ERROR;
+ }
+
+ /* Disable region processing */
+ CLEAR_BIT( region->REG_CONFIGR, OTFDEC_REG_CONFIGR_REG_ENABLE);
+
+ /* Release Lock */
+ __HAL_UNLOCK(hotfdec);
+
+ /* Status is okay */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup OTFDEC_Exported_Functions_Group4 Peripheral State and Status functions
+ * @brief Peripheral State functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the OTFDEC state.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @retval HAL state
+ */
+HAL_OTFDEC_StateTypeDef HAL_OTFDEC_GetState(OTFDEC_HandleTypeDef *hotfdec)
+{
+ return hotfdec->State;
+}
+
+
+/**
+ * @brief Return region keys CRC.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param RegionIndex index of region the keys CRC of which is read
+ * @retval Key CRC
+ */
+uint32_t HAL_OTFDEC_RegionGetKeyCRC(OTFDEC_HandleTypeDef *hotfdec, uint32_t RegionIndex)
+{
+ OTFDEC_Region_TypeDef * region;
+ uint32_t address;
+ uint32_t keycrc;
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+ assert_param(IS_OTFDEC_REGIONINDEX(RegionIndex));
+
+ address = (uint32_t)(hotfdec->Instance) + 0x20U + (0x30U * RegionIndex);
+ region = (OTFDEC_Region_TypeDef *)address;
+
+ keycrc = (READ_REG( region->REG_CONFIGR )) & OTFDEC_REG_CONFIGR_KEYCRC;
+
+ keycrc >>= OTFDEC_REG_CONFIGR_KEYCRC_Pos;
+
+ return keycrc;
+}
+
+/**
+ * @brief Return region configuration parameters.
+ * @param hotfdec pointer to an OTFDEC_HandleTypeDef structure that contains
+ * the configuration information for OTFDEC module
+ * @param RegionIndex index of region the configuration of which is read
+ * @param Config pointer on structure that will be filled up with the region configuration parameters
+ * @retval HAL state
+ */
+HAL_StatusTypeDef HAL_OTFDEC_RegionGetConfig(OTFDEC_HandleTypeDef *hotfdec, uint32_t RegionIndex, OTFDEC_RegionConfigTypeDef *Config)
+{
+ OTFDEC_Region_TypeDef * region;
+ uint32_t address;
+
+ /* Check the parameters */
+ assert_param(IS_OTFDEC_ALL_INSTANCE(hotfdec->Instance));
+ assert_param(IS_OTFDEC_REGIONINDEX(RegionIndex));
+
+ if (Config == NULL)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Take Lock */
+ __HAL_LOCK(hotfdec);
+
+ address = (uint32_t)(hotfdec->Instance) + 0x20U + (0x30U * RegionIndex);
+ region = (OTFDEC_Region_TypeDef *)address;
+
+ /* Read Nonce */
+ Config->Nonce[0] = READ_REG(region->REG_NONCER0);
+ Config->Nonce[1] = READ_REG(region->REG_NONCER1);
+
+ /* Read Addresses */
+ Config->StartAddress = READ_REG(region->REG_START_ADDR);
+ Config->EndAddress = READ_REG(region->REG_END_ADDR);
+
+ /* Read Version */
+ Config->Version = (uint16_t)(READ_REG(region->REG_CONFIGR) & OTFDEC_REG_CONFIGR_VERSION) >> OTFDEC_REG_CONFIGR_VERSION_Pos;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hotfdec);
+
+ /* Status is okay */
+ return HAL_OK;
+ }
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* OTFDEC1 */
+
+#endif /* HAL_OTFDEC_MODULE_ENABLED */
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_pcd.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pcd.c
new file mode 100644
index 0000000000..3a847e8757
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pcd.c
@@ -0,0 +1,2201 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ @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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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)
+{
+ USB_OTG_GlobalTypeDef *USBx;
+ 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));
+
+ USBx = 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 DMA mode for FS instance */
+ if ((USBx->CID & (0x1U << 8)) == 0U)
+ {
+ hpcd->Init.dma_enable = 0U;
+ }
+
+ /* 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*/
+ (void)USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE);
+
+ /* 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 */
+ (void)HAL_PCD_Stop(hpcd);
+
+#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 OTG 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 callabck 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 OTG 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)
+{
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+ __HAL_LOCK(hpcd);
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+ if ((hpcd->Init.battery_charging_enable == 1U) &&
+ (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
+ {
+ /* Enable USB Transceiver */
+ USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
+ }
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+ (void)USB_DevConnect(hpcd->Instance);
+ __HAL_PCD_ENABLE(hpcd);
+ __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)
+{
+ __HAL_LOCK(hpcd);
+ __HAL_PCD_DISABLE(hpcd);
+
+ if (USB_StopDevice(hpcd->Instance) != HAL_OK)
+ {
+ __HAL_UNLOCK(hpcd);
+ return HAL_ERROR;
+ }
+
+ (void)USB_DevDisconnect(hpcd->Instance);
+ __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;
+ uint32_t i, ep_intr, epint, epnum;
+ uint32_t fifoemptymsk, temp;
+ USB_OTG_EPTypeDef *ep;
+
+ /* ensure that we are in device mode */
+ if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
+ {
+ /* avoid spurious interrupt */
+ if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
+ {
+ return;
+ }
+
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
+ {
+ /* incorrect mode, acknowledge the interrupt */
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
+ }
+
+ /* Handle RxQLevel Interrupt */
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
+ {
+ USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+
+ temp = USBx->GRXSTSP;
+
+ ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
+
+ if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
+ {
+ if ((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
+ {
+ (void)USB_ReadPacket(USBx, ep->xfer_buff,
+ (uint16_t)((temp & USB_OTG_GRXSTSP_BCNT) >> 4));
+
+ ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
+ ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
+ }
+ }
+ else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
+ {
+ (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
+ ep->xfer_count += (temp & 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 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)
+ {
+ 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_INEP(i)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
+ 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 Incomplete ISO IN Interrupt */
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
+ {
+ /* Keep application checking the corresponding Iso IN endpoint
+ causing the incomplete Interrupt */
+ epnum = 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 */
+
+ __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))
+ {
+ /* Keep application checking the corresponding Iso OUT endpoint
+ causing the incomplete Interrupt */
+ epnum = 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 */
+
+ __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))
+ {
+ temp = hpcd->Instance->GOTGINT;
+
+ if ((temp & 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 |= temp;
+ }
+ }
+}
+#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)
+{
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+ __HAL_LOCK(hpcd);
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+ if ((hpcd->Init.battery_charging_enable == 1U) &&
+ (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
+ {
+ /* Enable USB Transceiver */
+ USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
+ }
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+ (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)
+{
+ __HAL_LOCK(hpcd);
+ (void)USB_DevDisconnect(hpcd->Instance);
+ __HAL_UNLOCK(hpcd);
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the USB Device address.
+ * @param hpcd PCD handle
+ * @param address new device address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
+{
+ __HAL_LOCK(hpcd);
+ 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 = ep_mps;
+ 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;
+ }
+
+ if ((ep_addr & EP_ADDR_MSK) == 0U)
+ {
+ (void)USB_EP0StartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
+ }
+ else
+ {
+ (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 *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;
+ }
+
+ if ((ep_addr & EP_ADDR_MSK) == 0U)
+ {
+ (void)USB_EP0StartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
+ }
+ else
+ {
+ (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 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 *hpcd)
+{
+ return hpcd->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* 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_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t gSNPSiD = *(__IO 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
+ {
+ /* out data packet received over EP0 */
+ hpcd->OUT_ep[epnum].xfer_count =
+ hpcd->OUT_ep[epnum].maxpacket -
+ (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);
+
+ hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket;
+
+ 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, 1U, (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 */
+ }
+ }
+ 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)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t gSNPSiD = *(__IO 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 */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_pcd_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pcd_ex.c
new file mode 100644
index 0000000000..17d3d5b05a
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pcd_ex.c
@@ -0,0 +1,348 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 Detect flag or a timeout is happen*/
+ while ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == 0U)
+ {
+ /* Check for the Timeout */
+ 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 */
+
+ return;
+ }
+ }
+
+ /* Right response got */
+ HAL_Delay(200U);
+
+ /* 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);
+
+#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 tranceiver */
+ 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 */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_pssi.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pssi.c
new file mode 100644
index 0000000000..e14f97f916
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pssi.c
@@ -0,0 +1,1798 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_pssi.c
+ * @author MCD Application Team
+ * @brief PSSI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Parallel Synchronous Slave Interface (PSSI) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and Errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The PSSI HAL driver can be used as follows:
+
+ (#) Declare a PSSI_HandleTypeDef handle structure, for example:
+ PSSI_HandleTypeDef hpssi;
+
+ (#) Initialize the PSSI low level resources by implementing the @ref HAL_PSSI_MspInit() API:
+ (##) Enable the PSSIx interface clock
+ (##) PSSI pins configuration
+ (+++) Enable the clock for the PSSI GPIOs
+ (+++) Configure PSSI pins as alternate function open-drain
+ (##) NVIC configuration if you need to use interrupt process
+ (+++) Configure the PSSIx interrupt priority
+ (+++) Enable the NVIC PSSI IRQ Channel
+ (##) DMA Configuration if you need to use DMA process
+ (+++) Declare DMA_HandleTypeDef handles structure for the transmit and receive
+ (+++) Enable the DMAx interface clock
+ (+++) Configure the DMA handle parameters
+ (+++) Configure the DMA Tx and Rx
+ (+++) Associate the initialized DMA handle to the hpssi DMA Tx and Rx handle
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on
+ the DMA Tx and Rx
+
+ (#) Configure the Communication Bus Width, Control Signals, Input Polarity and Output Polarity
+ in the hpssi Init structure.
+
+ (#) Initialize the PSSI registers by calling the @ref HAL_PSSI_Init(), configure also the low level Hardware
+ (GPIO, CLOCK, NVIC...etc) by calling the customized @ref HAL_PSSI_MspInit(&hpssi) API.
+
+
+ (#) For PSSI IO operations, two operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Transmit an amount of data by byte in blocking mode using @ref HAL_PSSI_Transmit()
+ (+) Receive an amount of data by byte in blocking mode using @ref HAL_PSSI_Receive()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Transmit an amount of data in non-blocking mode (DMA) using
+ @ref HAL_PSSI_Transmit_DMA()
+ (+) At transmission end of transfer, @ref HAL_PSSI_TxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_PSSI_TxCpltCallback()
+ (+) Receive an amount of data in non-blocking mode (DMA) using
+ @ref HAL_PSSI_Receive_DMA()
+ (+) At reception end of transfer, @ref HAL_PSSI_RxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_PSSI_RxCpltCallback()
+ (+) In case of transfer Error, @ref HAL_PSSI_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer @ref HAL_PSSI_ErrorCallback()
+ (+) Abort a PSSI process communication with Interrupt using @ref HAL_PSSI_Abort_IT()
+ (+) End of abort process, @ref HAL_PSSI_AbortCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_PSSI_AbortCpltCallback()
+
+ *** PSSI HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in PSSI HAL driver.
+
+ (+) @ref HAL_PSSI_ENABLE : Enable the PSSI peripheral
+ (+) @ref HAL_PSSI_DISABLE : Disable the PSSI peripheral
+ (+) @ref HAL_PSSI_GET_FLAG : Check whether the specified PSSI flag is set or not
+ (+) @ref HAL_PSSI_CLEAR_FLAG : Clear the specified PSSI pending flag
+ (+) @ref HAL_PSSI_ENABLE_IT : Enable the specified PSSI interrupt
+ (+) @ref HAL_PSSI_DISABLE_IT : Disable the specified PSSI interrupt
+
+ *** Callback registration ***
+ =============================================
+ Use Functions @ref HAL_PSSI_RegisterCallback() or @ref HAL_PSSI_RegisterAddrCallback()
+ to register an interrupt callback.
+
+ Function @ref HAL_PSSI_RegisterCallback() allows to register following callbacks:
+ (+) TxCpltCallback : callback for transmission end of transfer.
+ (+) RxCpltCallback : callback for 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.
+
+
+ Use function @ref HAL_PSSI_UnRegisterCallback to reset a callback to the default
+ weak function.
+ @ref HAL_PSSI_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxCpltCallback : callback for transmission end of transfer.
+ (+) RxCpltCallback : callback for 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.
+
+
+ By default, after the @ref HAL_PSSI_Init() and when the state is @ref HAL_PSSI_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples @ref HAL_PSSI_TxCpltCallback(), @ref HAL_PSSI_RxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the @ref HAL_PSSI_Init()/ @ref HAL_PSSI_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ If MspInit or MspDeInit are not null, the @ref HAL_PSSI_Init()/ @ref HAL_PSSI_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+
+ Callbacks can be registered/unregistered in @ref HAL_PSSI_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in @ref HAL_PSSI_STATE_READY or @ref HAL_PSSI_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 @ref HAL_PSSI_RegisterCallback() before calling @ref HAL_PSSI_DeInit()
+ or @ref HAL_PSSI_Init() function.
+
+
+ [..]
+ (@) You can refer to the PSSI HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PSSI PSSI
+ * @brief PSSI HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PSSI_MODULE_ENABLED
+#if defined(PSSI)
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup PSSI_Private_Define PSSI Private Define
+ * @{
+ */
+
+
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+
+/** @defgroup PSSI_Private_Functions PSSI Private Functions
+ * @{
+ */
+/* Private functions to handle DMA transfer */
+void PSSI_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+void PSSI_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+void PSSI_DMAError(DMA_HandleTypeDef *hdma);
+void PSSI_DMAAbort(DMA_HandleTypeDef *hdma);
+
+
+/* Private functions to handle IT transfer */
+static void PSSI_Error(PSSI_HandleTypeDef *hpssi, uint32_t ErrorCode);
+
+/* Private functions to handle flags during polling transfer */
+static HAL_StatusTypeDef PSSI_WaitOnStatusUntilTimeout(PSSI_HandleTypeDef *hpssi, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart);
+
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup PSSI_Exported_Functions PSSI Exported Functions
+ * @{
+ */
+
+/** @defgroup PSSI_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 PSSIx peripheral:
+
+ (+) User must implement HAL_PSSI_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_PSSI_Init() to configure the selected device with
+ the selected configuration:
+ (++) Data Width
+ (++) Control Signals
+ (++) Input Clock polarity
+ (++) Output Clock polarity
+
+ (+) Call the function HAL_PSSI_DeInit() to restore the default configuration
+ of the selected PSSIx peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the PSSI according to the specified parameters
+ * in the PSSI_InitTypeDef and initialize the associated handle.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PSSI_Init(PSSI_HandleTypeDef *hpssi)
+{
+ /* Check the PSSI handle allocation */
+ if (hpssi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_PSSI_ALL_INSTANCE(hpssi->Instance));
+ assert_param(IS_PSSI_CONTROL_SIGNAL(hpssi->Init.ControlSignal));
+ assert_param(IS_PSSI_BUSWIDTH(hpssi->Init.BusWidth));
+ assert_param(IS_PSSI_CLOCK_POLARITY(hpssi->Init.ClockPolarity));
+ assert_param(IS_PSSI_DE_POLARITY(hpssi->Init.DataEnablePolarity));
+ assert_param(IS_PSSI_RDY_POLARITY(hpssi->Init.ReadyPolarity));
+
+ if (hpssi->State == HAL_PSSI_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hpssi->Lock = HAL_UNLOCKED;
+
+ /* Init the PSSI Callback settings */
+ hpssi->TxCpltCallback = HAL_PSSI_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ hpssi->RxCpltCallback = HAL_PSSI_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ hpssi->ErrorCallback = HAL_PSSI_ErrorCallback; /* Legacy weak ErrorCallback */
+ hpssi->AbortCpltCallback = HAL_PSSI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+
+ if (hpssi->MspInitCallback == NULL)
+ {
+ hpssi->MspInitCallback = HAL_PSSI_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ hpssi->MspInitCallback(hpssi);
+
+ }
+
+ hpssi->State = HAL_PSSI_STATE_BUSY;
+
+ /* Disable the selected PSSI peripheral */
+ HAL_PSSI_DISABLE(hpssi);
+
+ /*---------------------------- PSSIx CR Configuration ----------------------*/
+ /* Configure PSSIx: Control Signal and Bus Width*/
+
+ MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DERDYCFG|PSSI_CR_EDM|PSSI_CR_DEPOL|PSSI_CR_RDYPOL,
+ hpssi->Init.ControlSignal|hpssi->Init.DataEnablePolarity|hpssi->Init.ReadyPolarity|hpssi->Init.BusWidth);
+
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the PSSI peripheral.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PSSI_DeInit(PSSI_HandleTypeDef *hpssi)
+{
+ /* Check the PSSI handle allocation */
+ if (hpssi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_PSSI_ALL_INSTANCE(hpssi->Instance));
+
+ hpssi->State = HAL_PSSI_STATE_BUSY;
+
+ /* Disable the PSSI Peripheral Clock */
+ HAL_PSSI_DISABLE(hpssi);
+
+ if (hpssi->MspDeInitCallback == NULL)
+ {
+ hpssi->MspDeInitCallback = HAL_PSSI_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ hpssi->MspDeInitCallback(hpssi);
+
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
+ hpssi->State = HAL_PSSI_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpssi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the PSSI MSP.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval None
+ */
+__weak void HAL_PSSI_MspInit(PSSI_HandleTypeDef *hpssi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpssi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PSSI_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the PSSI MSP.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval None
+ */
+__weak void HAL_PSSI_MspDeInit(PSSI_HandleTypeDef *hpssi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpssi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PSSI_MspDeInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Register a User PSSI Callback
+ * To be used instead of the weak predefined callback
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_PSSI_TX_COMPLETE_CB_ID Tx Transfer completed callback ID
+ * @arg @ref HAL_PSSI_RX_COMPLETE_CB_ID Rx Transfer completed callback ID
+ * @arg @ref HAL_PSSI_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_PSSI_ABORT_CB_ID Abort callback ID
+ * @arg @ref HAL_PSSI_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_PSSI_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PSSI_RegisterCallback(PSSI_HandleTypeDef *hpssi, HAL_PSSI_CallbackIDTypeDef CallbackID, pPSSI_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hpssi);
+
+ if (HAL_PSSI_STATE_READY == hpssi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_PSSI_TX_COMPLETE_CB_ID :
+ hpssi->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_PSSI_RX_COMPLETE_CB_ID :
+ hpssi->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_PSSI_ERROR_CB_ID :
+ hpssi->ErrorCallback = pCallback;
+ break;
+
+ case HAL_PSSI_ABORT_CB_ID :
+ hpssi->AbortCpltCallback = pCallback;
+ break;
+
+ case HAL_PSSI_MSPINIT_CB_ID :
+ hpssi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_PSSI_MSPDEINIT_CB_ID :
+ hpssi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_PSSI_STATE_RESET == hpssi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_PSSI_MSPINIT_CB_ID :
+ hpssi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_PSSI_MSPDEINIT_CB_ID :
+ hpssi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpssi);
+ return status;
+}
+
+/**
+ * @brief Unregister an PSSI Callback
+ * PSSI callback is redirected to the weak predefined callback
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_PSSI_TX_COMPLETE_CB_ID Tx Transfer completed callback ID
+ * @arg @ref HAL_PSSI_RX_COMPLETE_CB_ID Rx Transfer completed callback ID
+ * @arg @ref HAL_PSSI_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_PSSI_ABORT_CB_ID Abort callback ID
+ * @arg @ref HAL_PSSI_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_PSSI_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PSSI_UnRegisterCallback(PSSI_HandleTypeDef *hpssi, HAL_PSSI_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hpssi);
+
+ if (HAL_PSSI_STATE_READY == hpssi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_PSSI_TX_COMPLETE_CB_ID :
+ hpssi->TxCpltCallback = HAL_PSSI_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ break;
+
+ case HAL_PSSI_RX_COMPLETE_CB_ID :
+ hpssi->RxCpltCallback = HAL_PSSI_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ break;
+
+ case HAL_PSSI_ERROR_CB_ID :
+ hpssi->ErrorCallback = HAL_PSSI_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_PSSI_ABORT_CB_ID :
+ hpssi->AbortCpltCallback = HAL_PSSI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ break;
+
+ case HAL_PSSI_MSPINIT_CB_ID :
+ hpssi->MspInitCallback = HAL_PSSI_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_PSSI_MSPDEINIT_CB_ID :
+ hpssi->MspDeInitCallback = HAL_PSSI_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_PSSI_STATE_RESET == hpssi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_PSSI_MSPINIT_CB_ID :
+ hpssi->MspInitCallback = HAL_PSSI_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_PSSI_MSPDEINIT_CB_ID :
+ hpssi->MspDeInitCallback = HAL_PSSI_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpssi);
+ return status;
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup PSSI_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 PSSI 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 DMA.
+ These functions return the status of the transfer startup.
+ The end of the data processing will be indicated through the
+ dedicated the DMA IRQ .
+
+ (#) Blocking mode functions are :
+ (++) HAL_PSSI_Transmit()
+ (++) HAL_PSSI_Receive()
+
+ (#) No-Blocking mode functions with DMA are :
+ (++) HAL_PSSI_Transmit_DMA()
+ (++) HAL_PSSI_Receive_DMA()
+
+ (#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
+ (++) HAL_PSSI_TxCpltCallback()
+ (++) HAL_PSSI_RxCpltCallback()
+ (++) HAL_PSSI_ErrorCallback()
+ (++) HAL_PSSI_AbortCpltCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmits in master mode an amount of data in blocking mode.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent (in bytes)
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PSSI_Transmit(PSSI_HandleTypeDef *hpssi, uint8_t *pData, uint32_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t transfer_size = Size;
+
+#if defined (__GNUC__)
+ __IO uint16_t *pdr_16bits = (__IO uint16_t *)(&(hpssi->Instance->DR));
+#endif /* __GNUC__ */
+
+ if (((hpssi->Init.DataWidth == HAL_PSSI_8BITS) && (hpssi->Init.BusWidth != HAL_PSSI_8LINES)) ||
+ ((hpssi->Init.DataWidth == HAL_PSSI_16BITS) && ((Size%2U) != 0U)) ||
+ ((hpssi->Init.DataWidth == HAL_PSSI_32BITS) && ((Size%4U) != 0U)))
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NOT_SUPPORTED;
+ return HAL_ERROR;
+ }
+ if (hpssi->State == HAL_PSSI_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hpssi);
+
+ hpssi->State = HAL_PSSI_STATE_BUSY;
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
+
+ /* Disable the selected PSSI peripheral */
+ HAL_PSSI_DISABLE(hpssi);
+
+ /* Configure transfer parameters */
+ hpssi->Instance->CR |= PSSI_CR_OUTEN_OUTPUT |
+ ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?0U:PSSI_CR_CKPOL);
+ /* DMA Disable */
+ hpssi->Instance->CR &= PSSI_CR_DMA_DISABLE;
+
+ /* Enable the selected PSSI peripheral */
+ HAL_PSSI_ENABLE(hpssi);
+
+ if (hpssi->Init.DataWidth == HAL_PSSI_8BITS)
+ {
+ uint8_t *pbuffer = pData;
+ while (transfer_size > 0U)
+ {
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+ /* Wait until Fifo is ready to transfer one byte flag is set */
+ if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT1B, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+ /* Write data to DR */
+ *(__IO uint8_t *)(&hpssi->Instance->DR) = *(uint8_t *)pbuffer;
+
+ /* Increment Buffer pointer */
+ pbuffer++;
+
+ transfer_size--;
+ }
+ }
+ else if (hpssi->Init.DataWidth == HAL_PSSI_16BITS)
+ {
+ uint16_t *pbuffer = (uint16_t *)pData;
+ while (transfer_size > 0U)
+ {
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+ /* Wait until Fifo is ready to transfer four bytes flag is set */
+ if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT4B, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+ /* Write data to DR */
+#if defined (__GNUC__)
+ *pdr_16bits = *pbuffer;
+#else
+ *(__IO uint16_t *)((uint32_t)(&hpssi->Instance->DR)) = *pbuffer;
+#endif /* __GNUC__ */
+
+ /* Increment Buffer pointer */
+ pbuffer++;
+ transfer_size -= 2U;
+
+ }
+ }
+ else if (hpssi->Init.DataWidth == HAL_PSSI_32BITS)
+ {
+ uint32_t *pbuffer = (uint32_t *)pData;
+ while (transfer_size > 0U)
+ {
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+ /* Wait until Fifo is ready to transfer four bytes flag is set */
+ if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT4B, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+ /* Write data to DR */
+ *(__IO uint32_t *)(&hpssi->Instance->DR) = *pbuffer;
+
+ /* Increment Buffer pointer */
+ pbuffer++;
+ transfer_size -= 4U;
+ }
+
+ }
+ else
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NOT_SUPPORTED;
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+
+ /* Check Errors Flags */
+ if (HAL_PSSI_GET_FLAG(hpssi, PSSI_FLAG_OVR_RIS) != 0U)
+ {
+ HAL_PSSI_CLEAR_FLAG(hpssi, PSSI_FLAG_OVR_RIS);
+ HAL_PSSI_DISABLE(hpssi);
+ hpssi->ErrorCode = HAL_PSSI_ERROR_UNDER_RUN;
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+/**
+ * @brief Receives an amount of data in blocking mode.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be received (in bytes)
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PSSI_Receive(PSSI_HandleTypeDef *hpssi, uint8_t *pData, uint32_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t transfer_size = Size;
+#if defined (__GNUC__)
+ __IO uint16_t *pdr_16bits = (__IO uint16_t *)(&(hpssi->Instance->DR));
+#endif /* __GNUC__ */
+
+ if (((hpssi->Init.DataWidth == HAL_PSSI_8BITS) && (hpssi->Init.BusWidth != HAL_PSSI_8LINES)) ||
+ ((hpssi->Init.DataWidth == HAL_PSSI_16BITS) && ((Size%2U) != 0U)) ||
+ ((hpssi->Init.DataWidth == HAL_PSSI_32BITS) && ((Size%4U) != 0U)))
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NOT_SUPPORTED;
+ return HAL_ERROR;
+ }
+
+ if (hpssi->State == HAL_PSSI_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hpssi);
+
+ hpssi->State = HAL_PSSI_STATE_BUSY;
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
+
+ /* Disable the selected PSSI peripheral */
+ HAL_PSSI_DISABLE(hpssi);
+ /* Configure transfer parameters */
+ hpssi->Instance->CR |= PSSI_CR_OUTEN_INPUT |((hpssi->Init.ClockPolarity == HAL_PSSI_FALLING_EDGE)?0U:PSSI_CR_CKPOL);
+
+
+ /* DMA Disable */
+ hpssi->Instance->CR &= PSSI_CR_DMA_DISABLE;
+
+ /* Enable the selected PSSI peripheral */
+ HAL_PSSI_ENABLE(hpssi);
+ if (hpssi->Init.DataWidth == HAL_PSSI_8BITS)
+ {
+ uint8_t *pbuffer = pData;
+
+ while (transfer_size > 0U)
+ {
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+ /* Wait until Fifo is ready to receive one byte flag is set */
+ if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT1B, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+ /* Read data from DR */
+ *pbuffer = *(__IO uint8_t *)(&hpssi->Instance->DR);
+ pbuffer++;
+ transfer_size--;
+ }
+ }
+ else if (hpssi->Init.DataWidth == HAL_PSSI_16BITS)
+ {
+ uint16_t *pbuffer = (uint16_t *)pData;
+
+ while (transfer_size > 0U)
+ {
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+ /* Wait until Fifo is ready to receive four bytes flag is set */
+ if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT4B, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+
+ /* Read data from DR */
+#if defined (__GNUC__)
+ *pbuffer = *pdr_16bits;
+#else
+ *pbuffer = *(__IO uint16_t *)((uint32_t)&hpssi->Instance->DR);
+#endif /* __GNUC__ */
+
+ pbuffer++;
+ transfer_size -= 2U;
+
+ }
+ }
+ else if (hpssi->Init.DataWidth == HAL_PSSI_32BITS)
+ {
+ uint32_t *pbuffer = (uint32_t *)pData;
+
+ while (transfer_size > 0U)
+ {
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+ /* Wait until Fifo is ready to receive four bytes flag is set */
+ if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT4B, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+
+ /* Read data from DR */
+ *pbuffer = *(__IO uint32_t *)(&hpssi->Instance->DR);
+ pbuffer++;
+ transfer_size -= 4U;
+
+ }
+ }
+ else
+ {
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NOT_SUPPORTED;
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+ /* Check Errors Flags */
+
+ if (HAL_PSSI_GET_FLAG(hpssi, PSSI_FLAG_OVR_RIS) != 0U)
+ {
+ HAL_PSSI_CLEAR_FLAG(hpssi, PSSI_FLAG_OVR_RIS);
+ hpssi->ErrorCode = HAL_PSSI_ERROR_OVER_RUN;
+ __HAL_UNLOCK(hpssi);
+ return HAL_ERROR;
+ }
+
+
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with DMA
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent (in bytes)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PSSI_Transmit_DMA(PSSI_HandleTypeDef *hpssi, uint32_t *pData, uint32_t Size)
+{
+ HAL_StatusTypeDef dmaxferstatus;
+
+ if (hpssi->State == HAL_PSSI_STATE_READY)
+ {
+
+ /* Process Locked */
+ __HAL_LOCK(hpssi);
+
+ hpssi->State = HAL_PSSI_STATE_BUSY_TX;
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
+
+ /* Disable the selected PSSI peripheral */
+ HAL_PSSI_DISABLE(hpssi);
+
+ /* Prepare transfer parameters */
+ hpssi->pBuffPtr = pData;
+ hpssi->XferCount = Size;
+
+ if (hpssi->XferCount > PSSI_MAX_NBYTE_SIZE)
+ {
+ hpssi->XferSize = PSSI_MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hpssi->XferSize = hpssi->XferCount;
+ }
+
+ if (hpssi->XferSize > 0U)
+ {
+ if (hpssi->hdmatx != NULL)
+ {
+
+ /* Configure BusWidth */
+ if( hpssi->hdmatx->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE)
+ {
+ MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DMAEN|PSSI_CR_OUTEN|PSSI_CR_CKPOL,PSSI_CR_DMA_ENABLE | PSSI_CR_OUTEN_OUTPUT |
+ ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?0U:PSSI_CR_CKPOL));
+ }
+ else
+ {
+ MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DMAEN|PSSI_CR_OUTEN|PSSI_CR_CKPOL,PSSI_CR_DMA_ENABLE | hpssi->Init.BusWidth | PSSI_CR_OUTEN_OUTPUT |
+ ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?0U:PSSI_CR_CKPOL));
+ }
+
+ /* Set the PSSI DMA transfer complete callback */
+ hpssi->hdmatx->XferCpltCallback = PSSI_DMATransmitCplt;
+
+ /* Set the DMA error callback */
+ hpssi->hdmatx->XferErrorCallback = PSSI_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hpssi->hdmatx->XferHalfCpltCallback = NULL;
+ hpssi->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA */
+ dmaxferstatus = HAL_DMA_Start_IT(hpssi->hdmatx, (uint32_t)pData, (uint32_t)&hpssi->Instance->DR, hpssi->XferSize);
+ }
+ else
+ {
+ /* Update PSSI state */
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Update PSSI error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+
+
+ /* Update XferCount value */
+ hpssi->XferCount -= hpssi->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Note : The PSSI interrupts must be enabled after unlocking current process
+ to avoid the risk of PSSI interrupt handle execution before current
+ process unlock */
+ /* Enable ERR interrupt */
+ HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+
+ /* Enable DMA Request */
+ hpssi->Instance->CR |= PSSI_CR_DMA_ENABLE;
+ /* Enable the selected PSSI peripheral */
+ HAL_PSSI_ENABLE(hpssi);
+ }
+ else
+ {
+ /* Update PSSI state */
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Update PSSI error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Note : The PSSI interrupts must be enabled after unlocking current process
+ to avoid the risk of PSSI interrupt handle execution before current
+ process unlock */
+ /* Enable ERRinterrupt */
+ /* possible to enable all of these */
+
+ HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be received (in bytes)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PSSI_Receive_DMA(PSSI_HandleTypeDef *hpssi, uint32_t *pData, uint32_t Size)
+{
+
+ HAL_StatusTypeDef dmaxferstatus;
+
+ if (hpssi->State == HAL_PSSI_STATE_READY)
+ {
+
+ /* Disable the selected PSSI peripheral */
+ HAL_PSSI_DISABLE(hpssi);
+ /* Process Locked */
+ __HAL_LOCK(hpssi);
+
+ hpssi->State = HAL_PSSI_STATE_BUSY_RX;
+ hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hpssi->pBuffPtr = pData;
+ hpssi->XferCount = Size;
+
+ if (hpssi->XferCount > PSSI_MAX_NBYTE_SIZE)
+ {
+ hpssi->XferSize = PSSI_MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hpssi->XferSize = hpssi->XferCount;
+ }
+
+ if (hpssi->XferSize > 0U)
+ {
+ if (hpssi->hdmarx != NULL)
+ {
+
+ /* Configure BusWidth */
+ if( hpssi->hdmatx->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE)
+ {
+ MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DMAEN|PSSI_CR_OUTEN|PSSI_CR_CKPOL,PSSI_CR_DMA_ENABLE |
+ ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?PSSI_CR_CKPOL:0U));
+ }
+ else
+ {
+ MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DMAEN|PSSI_CR_OUTEN|PSSI_CR_CKPOL,PSSI_CR_DMA_ENABLE | hpssi->Init.BusWidth |
+ ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?PSSI_CR_CKPOL:0U));
+ }
+
+ /* Set the PSSI DMA transfer complete callback */
+ hpssi->hdmarx->XferCpltCallback = PSSI_DMAReceiveCplt;
+
+ /* Set the DMA error callback */
+ hpssi->hdmarx->XferErrorCallback = PSSI_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hpssi->hdmarx->XferHalfCpltCallback = NULL;
+ hpssi->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA */
+ dmaxferstatus = HAL_DMA_Start_IT(hpssi->hdmarx, (uint32_t)&hpssi->Instance->DR, (uint32_t)pData, hpssi->XferSize);
+ }
+ else
+ {
+ /* Update PSSI state */
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Update PSSI error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Update XferCount value */
+ hpssi->XferCount -= hpssi->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Note : The PSSI interrupts must be enabled after unlocking current process
+ to avoid the risk of PSSI interrupt handle execution before current
+ process unlock */
+ /* Enable ERR interrupt */
+ HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+
+ /* Enable DMA Request */
+ hpssi->Instance->CR |= PSSI_CR_DMA_ENABLE;
+ /* Enable the selected PSSI peripheral */
+ HAL_PSSI_ENABLE(hpssi);
+ }
+ else
+ {
+ /* Update PSSI state */
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Update PSSI error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Enable ERR,interrupt */
+ HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+
+/**
+ * @brief Abort a DMA process communication with Interrupt.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PSSI_Abort_DMA(PSSI_HandleTypeDef *hpssi)
+{
+
+ /* Process Locked */
+ __HAL_LOCK(hpssi);
+
+ /* Disable Interrupts */
+ HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+
+ /* Set State at HAL_PSSI_STATE_ABORT */
+ hpssi->State = HAL_PSSI_STATE_ABORT;
+
+ /* Abort DMA TX transfer if any */
+ if ((hpssi->Instance->CR & PSSI_CR_DMAEN) == PSSI_CR_DMAEN)
+ {
+ if (hpssi->State == HAL_PSSI_STATE_BUSY_TX)
+ {
+
+ hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
+
+ if (hpssi->hdmatx != NULL)
+ {
+ /* Set the PSSI DMA Abort callback :
+ will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
+ hpssi->hdmatx->XferAbortCallback = PSSI_DMAAbort;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hpssi->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hpssi->hdmatx->XferAbortCallback(hpssi->hdmatx);
+ }
+ }
+
+ }
+ /* Abort DMA RX transfer if any */
+ else if (hpssi->State == HAL_PSSI_STATE_BUSY_RX)
+ {
+
+ hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
+
+ if (hpssi->hdmarx != NULL)
+ {
+ /* Set the PSSI DMA Abort callback :
+ will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
+ hpssi->hdmarx->XferAbortCallback = PSSI_DMAAbort;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hpssi->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hpssi->hdma->XferAbortCallback function in case of error */
+ hpssi->hdmarx->XferAbortCallback(hpssi->hdmarx);
+ }
+ }
+ }
+ else
+ {
+ /* Call the error callback */
+ hpssi->ErrorCallback(hpssi);
+ }
+ }
+
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Note : The PSSI interrupts must be enabled after unlocking current process
+ to avoid the risk of PSSI interrupt handle execution before current
+ process unlock */
+ HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+
+ return HAL_OK;
+
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup PSSI_Exported_Functions_Group3 IRQ Handler and Callbacks
+ * @{
+ */
+
+/**
+ * @brief This function handles PSSI event interrupt request.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval None
+ */
+void HAL_PSSI_IRQHandler(PSSI_HandleTypeDef *hpssi)
+{
+ /* Overrun/ Underrun Errors */
+ if (HAL_PSSI_GET_FLAG(hpssi, PSSI_FLAG_OVR_MIS) != 0U)
+ {
+ /* Reset handle parameters */
+
+ hpssi->XferCount = 0U;
+
+ /* Disable all interrupts */
+ HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+
+
+ /* Abort DMA TX transfer if any */
+ if ((hpssi->Instance->CR & PSSI_CR_DMAEN) == PSSI_CR_DMAEN)
+ {
+ if (hpssi->State == HAL_PSSI_STATE_BUSY_TX)
+ {
+ /* Set new error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_UNDER_RUN;
+
+ hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
+
+ if (hpssi->hdmatx != NULL)
+ {
+ /* Set the PSSI DMA Abort callback :
+ will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
+ hpssi->hdmatx->XferAbortCallback = PSSI_DMAAbort;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hpssi->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hpssi->hdmatx->XferAbortCallback(hpssi->hdmatx);
+ }
+ }
+
+ }
+ /* Abort DMA RX transfer if any */
+ else if (hpssi->State == HAL_PSSI_STATE_BUSY_RX)
+ {
+ /* Set new error code */
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_OVER_RUN;
+
+ hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
+
+ if (hpssi->hdmarx != NULL)
+ {
+ /* Set the PSSI DMA Abort callback :
+ will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
+ hpssi->hdmarx->XferAbortCallback = PSSI_DMAAbort;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hpssi->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hpssi->hdma->XferAbortCallback function in case of error */
+ hpssi->hdmarx->XferAbortCallback(hpssi->hdmarx);
+ }
+ }
+ }
+ else
+ {
+ /* Call the corresponding callback to inform upper layer of the error */
+ hpssi->ErrorCallback(hpssi);
+ }
+ }
+
+ /* If state is an abort treatment on going, don't change state */
+ if (hpssi->State == HAL_PSSI_STATE_ABORT)
+ {
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ hpssi->AbortCpltCallback(hpssi);
+
+ }
+ else
+ {
+ /* Set HAL_PSSI_STATE_READY */
+ hpssi->State = HAL_PSSI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ hpssi->ErrorCallback(hpssi);
+
+ }
+
+ }
+}
+
+
+/**
+ * @brief Tx Transfer complete callback.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval None
+ */
+__weak void HAL_PSSI_TxCpltCallback(PSSI_HandleTypeDef *hpssi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpssi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PSSI_TxCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer complete callback.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval None
+ */
+__weak void HAL_PSSI_RxCpltCallback(PSSI_HandleTypeDef *hpssi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpssi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PSSI_RxCpltCallback can be implemented in the user file
+ */
+}
+
+
+/**
+ * @brief PSSI error callback.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval None
+ */
+__weak void HAL_PSSI_ErrorCallback(PSSI_HandleTypeDef *hpssi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpssi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PSSI_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief PSSI abort callback.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval None
+ */
+__weak void HAL_PSSI_AbortCpltCallback(PSSI_HandleTypeDef *hpssi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpssi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PSSI_AbortCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup PSSI_Exported_Functions_Group4 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 PSSI handle state.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @retval HAL state
+ */
+HAL_PSSI_StateTypeDef HAL_PSSI_GetState(PSSI_HandleTypeDef *hpssi)
+{
+ /* Return PSSI handle state */
+ return hpssi->State;
+}
+
+
+/**
+* @brief Return the PSSI error code.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+* @retval PSSI Error Code
+*/
+uint32_t HAL_PSSI_GetError(PSSI_HandleTypeDef *hpssi)
+{
+ return hpssi->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup PSSI_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief PSSI Errors process.
+ * @param hpssi PSSI handle.
+ * @param ErrorCode Error code to handle.
+ * @retval None
+ */
+static void PSSI_Error(PSSI_HandleTypeDef *hpssi, uint32_t ErrorCode)
+{
+
+ /* Reset handle parameters */
+
+ hpssi->XferCount = 0U;
+
+ /* Set new error code */
+ hpssi->ErrorCode |= ErrorCode;
+
+ /* Disable all interrupts */
+ HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+
+
+ /* Abort DMA TX transfer if any */
+ if ((hpssi->Instance->CR & PSSI_CR_DMAEN) == PSSI_CR_DMAEN)
+ {
+ if (hpssi->State == HAL_PSSI_STATE_BUSY_TX)
+ {
+ hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
+
+ if (hpssi->hdmatx != NULL)
+ {
+ /* Set the PSSI DMA Abort callback :
+ will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
+ hpssi->hdmatx->XferAbortCallback = PSSI_DMAAbort;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hpssi->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hpssi->hdmatx->XferAbortCallback(hpssi->hdmatx);
+ }
+ }
+
+ }
+ /* Abort DMA RX transfer if any */
+ else if (hpssi->State == HAL_PSSI_STATE_BUSY_RX)
+ {
+ hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
+
+ if (hpssi->hdmarx != NULL)
+ {
+ /* Set the PSSI DMA Abort callback :
+ will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
+ hpssi->hdmarx->XferAbortCallback = PSSI_DMAAbort;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hpssi->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hpssi->hdma->XferAbortCallback function in case of error */
+ hpssi->hdmarx->XferAbortCallback(hpssi->hdmarx);
+ }
+ }
+ }
+ else
+ {
+ /*Nothing to do*/
+ }
+ }
+
+ /* If state is an abort treatment on going, don't change state */
+ if (hpssi->State == HAL_PSSI_STATE_ABORT)
+ {
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+
+ hpssi->AbortCpltCallback(hpssi);
+
+ }
+ else
+ {
+ /* Set HAL_PSSI_STATE_READY */
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ hpssi->ErrorCallback(hpssi);
+
+ }
+}
+
+/**
+ * @brief DMA PSSI slave transmit process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+void PSSI_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ PSSI_HandleTypeDef *hpssi = (PSSI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+
+ uint32_t tmperror;
+
+
+ /* Disable Interrupts */
+ HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+
+ /* Store current volatile hpssi->ErrorCode, misra rule */
+ tmperror = hpssi->ErrorCode;
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if ((hpssi->State == HAL_PSSI_STATE_ABORT) || (tmperror != HAL_PSSI_ERROR_NONE))
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ PSSI_Error(hpssi, hpssi->ErrorCode);
+ }
+ /* hpssi->State == HAL_PSSI_STATE_BUSY_TX */
+ else
+ {
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+
+ hpssi->TxCpltCallback(hpssi);
+
+ }
+
+
+}
+
+/**
+ * @brief DMA PSSI master receive process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+void PSSI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ PSSI_HandleTypeDef *hpssi = (PSSI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+
+ uint32_t tmperror;
+
+
+ /* Disable Interrupts */
+ HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+
+ /* Store current volatile hpssi->ErrorCode, misra rule */
+ tmperror = hpssi->ErrorCode;
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if ((hpssi->State == HAL_PSSI_STATE_ABORT) || (tmperror != HAL_PSSI_ERROR_NONE))
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ PSSI_Error(hpssi, hpssi->ErrorCode);
+ }
+ /* hpssi->State == HAL_PSSI_STATE_BUSY_RX */
+ else
+ {
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ hpssi->RxCpltCallback(hpssi);
+
+ }
+
+
+}
+
+/**
+ * @brief DMA PSSI communication abort callback
+ * (To be called at end of DMA Abort procedure).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+void PSSI_DMAAbort(DMA_HandleTypeDef *hdma)
+{
+ PSSI_HandleTypeDef *hpssi = (PSSI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+
+ /* Reset AbortCpltCallback */
+ hpssi->hdmatx->XferAbortCallback = NULL;
+ hpssi->hdmarx->XferAbortCallback = NULL;
+
+ /* Check if come from abort from user */
+ if (hpssi->State == HAL_PSSI_STATE_ABORT)
+ {
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+
+ hpssi->AbortCpltCallback(hpssi);
+
+ }
+ else
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ hpssi->ErrorCallback(hpssi);
+ }
+}
+
+/**
+ * @brief This function handles PSSI Communication Timeout.
+ * @param hpssi Pointer to a PSSI_HandleTypeDef structure that contains
+ * the configuration information for the specified PSSI.
+ * @param Flag Specifies the PSSI flag to check.
+ * @param Status The new Flag status (SET or RESET).
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef PSSI_WaitOnStatusUntilTimeout(PSSI_HandleTypeDef *hpssi, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart)
+{
+ while ((HAL_PSSI_GET_STATUS(hpssi, Flag) & Flag) == (uint32_t)Status)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hpssi->ErrorCode |= HAL_PSSI_ERROR_TIMEOUT;
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ return HAL_OK;
+}
+void PSSI_DMAError(DMA_HandleTypeDef *hdma)
+{
+ PSSI_HandleTypeDef *hpssi = (PSSI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
+
+ uint32_t tmperror;
+
+
+ /* Disable the selected PSSI peripheral */
+ HAL_PSSI_DISABLE(hpssi);
+
+ /* Disable Interrupts */
+ HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
+
+ /* Store current volatile hpssi->ErrorCode, misra rule */
+ tmperror = hpssi->ErrorCode;
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if ((hpssi->State == HAL_PSSI_STATE_ABORT) || (tmperror != HAL_PSSI_ERROR_NONE))
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ PSSI_Error(hpssi, hpssi->ErrorCode);
+ }
+ else
+ {
+ hpssi->State = HAL_PSSI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hpssi);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ hpssi->ErrorCallback(hpssi);
+
+ }
+
+}
+
+
+
+/**
+ * @}
+ */
+#endif /* PSSI */
+#endif /* HAL_PSSI_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_pwr.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pwr.c
new file mode 100644
index 0000000000..43d9052a2c
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pwr.c
@@ -0,0 +1,868 @@
+/**
+ ******************************************************************************
+ * @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.
+ @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.
+ (+) STM32H743, STM32H753, STM32H742 and STM32H750 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.
+ (+) STM32H7AxxQ, STM32H7BxxQ, 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 decribed 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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 (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.
+ * @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.
+ * @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));
+
+ /* 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 regiter 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
+ * regiter 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.
+ * @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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_pwr_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pwr_ex.c
new file mode 100644
index 0000000000..82288f9e2f
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_pwr_ex.c
@@ -0,0 +1,2100 @@
+/**
+ ******************************************************************************
+ * @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
+ @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 functionnalities.
+
+ (#) 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
+ STM32H7AxxQ, STM32H7BxxQ, 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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 */
+#define PWR_EXTI_WAKEUP_PINS_MASK (EXTI_IMR2_IM55 | EXTI_IMR2_IM56 |\
+ EXTI_IMR2_IM57 | EXTI_IMR2_IM58 |\
+ EXTI_IMR2_IM59 | EXTI_IMR2_IM60)
+
+/* 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.
+ * @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.
+ * @note For STM32H7x3, STM32H7x5, STM32H7x7, STM32H742 and STM32H750 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.
+ * @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.
+ * @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 (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);
+ }
+#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 domain to DSTOP mode.
+ (+++) PWR_D2_DOMAIN : Enters D2 domain to DSTOP mode.
+ (+++) PWR_D3_DOMAIN : Enters D3 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 domain to DSTANDBY mode.
+ (+++) PWR_D2_DOMAIN : Enters D2 domain to DSTANDBY mode.
+ (+++) PWR_D3_DOMAIN : Enters D3 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)
+ {
+ /* Keep DSTOP mode when D2 domain enters Deepsleep */
+ CLEAR_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 stop
+ mode will not be performed
+ */
+ return;
+ }
+
+ /* 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);
+#endif /* defined (DUAL_CORE) */
+ }
+#endif /* defined (PWR_CPUCR_PDDS_D2) */
+ else
+ {
+ /* Keep DSTOP mode when D3/SRD domain enters Deepsleep */
+ CLEAR_BIT (PWR->CPUCR, PWR_CPUCR_PDDS_D3);
+ }
+}
+
+/**
+ * @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.
+ * @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 (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.
+ * @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.
+ * @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.
+ * @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 ();
+ }
+ 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 ();
+ }
+ 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 ();
+ }
+ 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 ();
+ }
+ 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
+ */
+}
+
+/**
+ * @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
+ */
+}
+
+/**
+ * @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
+ */
+}
+
+/**
+ * @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
+ */
+}
+
+/**
+ * @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 (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 ();
+
+ /* 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 ();
+
+ /* 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 ();
+
+ /* 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 ();
+
+ /* 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 */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_qspi.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_qspi.c
new file mode 100644
index 0000000000..b655c6e1d5
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_qspi.c
@@ -0,0 +1,2645 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ *
+ @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 paramters 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 @ref MDMA_Source_increment_mode (Except the MDMA_SRC_INC_DOUBLEWORD).
+ (+) The SourceDataSize must be a value of @ref MDMA Source data size (Except the MDMA_SRC_DATASIZE_DOUBLEWORD)
+ aligned with @ref MDMA_Source_increment_mode .
+ (+) The DestDataSize must be a value of @ref 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 @ref MDMA_Destination_increment_mode (Except the MDMA_DEST_INC_DOUBLEWORD).
+ (+) The SourceDataSize must be a value of @ref MDMA Source data size (Except the MDMA_SRC_DATASIZE_DOUBLEWORD) .
+ (+) The DestDataSize must be a value of @ref MDMA Destination data size (Except the MDMA_DEST_DATASIZE_DOUBLEWORD)
+ aligned with @ref 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_AbortIT() 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 @ref 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 @ref HAL_QSPI_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) 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 @ref HAL_QSPI_Init and if the state is HAL_QSPI_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_QSPI_Init
+ and @ref HAL_QSPI_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_QSPI_Init and @ref 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 @ref HAL_QSPI_RegisterCallback before calling @ref HAL_QSPI_DeInit
+ or @ref 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 (surcharged) 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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 the DMA transfer by clearing the DMAEN bit in the QSPI CR register */
+ 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 the DMA transfer by clearing the DMAEN bit in the QSPI CR register */
+ 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 the DMA transfer by clearing the DMAEN bit in the QSPI CR register */
+ 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 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);
+
+ /* Enable the QSPI transfer error Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE);
+
+ /* Enable the MDMA transfer by setting the DMAEN bit in the QSPI CR register */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+ }
+ else
+ {
+ 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 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);
+
+ /* Enable the QSPI transfer error Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE);
+
+ /* Enable the MDMA transfer by setting the DMAEN bit in the QSPI CR register */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+ }
+ else
+ {
+ 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 instead of the weak (surcharged) 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 (surcharged) 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(QSPI_HandleTypeDef *hqspi)
+{
+ /* Return QSPI handle state */
+ return hqspi->State;
+}
+
+/**
+* @brief Return the QSPI error code.
+* @param hqspi : QSPI handle
+* @retval QSPI Error Code
+*/
+uint32_t HAL_QSPI_GetError(QSPI_HandleTypeDef *hqspi)
+{
+ return hqspi->ErrorCode;
+}
+
+/**
+* @brief Abort the current transmission.
+* @param hqspi : QSPI handle
+* @retval HAL status
+*/
+HAL_StatusTypeDef HAL_QSPI_Abort(QSPI_HandleTypeDef *hqspi)
+{
+ HAL_StatusTypeDef status = HAL_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 the DMA transfer by clearing the DMAEN bit in the QSPI CR register */
+ 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;
+ }
+ }
+
+ /* 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;
+ }
+ }
+
+ 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 the DMA transfer by clearing the DMAEN bit in the QSPI CR register */
+ 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
+ {
+ /* 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);
+ }
+ }
+ 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(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;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @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 the MDMA transfer by clearing the DMAEN bit in the QSPI CR register */
+ 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));
+ }
+ }
+ 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));
+ }
+ }
+ }
+ 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));
+ }
+ }
+ 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));
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_QSPI_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined(QUADSPI) */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_ramecc.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_ramecc.c
new file mode 100644
index 0000000000..fd2776fb8d
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_ramecc.c
@@ -0,0 +1,692 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_ramecc.c
+ * @author MCD Application Team
+ * @brief RAMECC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the RAM ECC monitoring (RAMECC) peripheral:
+ * + Initialization and de-initialization functions
+ * + Monitoring operation functions
+ * + Error informations functions
+ * + State and error functions
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Enable and latch error informations through HAL_RAMECC_Init().
+
+ (#) For a given Monitor, enable and disable interrupt through
+ HAL_RAMECC_EnableNotifiaction().
+ To enable a notification for a given RAMECC instance, use global
+ interrupts.
+ To enable a notification for only RAMECC monitor, use monitor interrupts.
+ All possible notifications are defined in the driver header file under
+ RAMECC_Interrupt group.
+
+ *** Silent mode ***
+ ===================
+ [..]
+ (+) Use HAL_RAMECC_StartMonitor() to start RAMECC latch failing
+ information without enabling any notification.
+
+ *** Interrupt mode ***
+ ======================
+ [..]
+ (+) Use HAL_RAMECC_EnableNotifiaction() to enable interrupts for a
+ given error.
+ (+) Configure the RAMECC interrupt priority using
+ HAL_NVIC_SetPriority().
+ (+) Enable the RAMECC IRQ handler using HAL_NVIC_EnableIRQ().
+
+ *** Failing informations ***
+ ======================
+ [..]
+ (#) Use HAL_RAMECC_GetFailingAddress() function to return the RAMECC
+ failing address.
+ (#) Use HAL_RAMECC_GetFailingDataLow() function to return the RAMECC
+ failing data low.
+ (#) Use HAL_RAMECC_GetFailingDataHigh() function to return the RAMECC
+ failing data high.
+ (#) Use HAL_RAMECC_GetHammingErrorCode() function to return the RAMECC
+ Hamming bits injected.
+ (#) Use HAL_RAMECC_IsECCSingleErrorDetected() function to check if a single
+ error was detected and corrected.
+ (#) Use HAL_RAMECC_IsECCDoubleErrorDetected() function to check if a double
+ error was dedetected.
+
+ *** RAMECC HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of used macros in RAMECC HAL driver.
+
+ (+) __HAL_RAMECC_ENABLE_IT : Enable the specified ECCRAM Monitor
+ interrupts.
+ (+) __HAL_RAMECC_DISABLE_IT : Disable the specified ECCRAM Monitor
+ interrupts.
+ (+) __HAL_RAMECC_GET_FLAG : Return the current RAMECC Monitor selected
+ flag.
+ (+) __HAL_RAMECC_CLEAR_FLAG : Clear the current RAMECC Monitor selected
+ flag.
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RAMECC RAMECC
+ * @brief RAMECC HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RAMECC_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup RAMECC_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup RAMECC_Exported_Functions_Group1
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..]
+ This section provides functions allowing to initialize the RAMECC Monitor.
+ [..]
+ The HAL_RAMECC_Init() function follows the RAMECC configuration procedures
+ as described in reference manual.
+ The HAL_RAMECC_DeInit() function allows to deinitialize the RAMECC monitor.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the RAMECC by clearing flags and disabling interrupts.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_RAMECC_Init (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the RAMECC peripheral handle */
+ if (hramecc == NULL)
+ {
+ /* Return HAL status */
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_BUSY;
+
+ /* Disable RAMECC monitor */
+ hramecc->Instance->CR &= ~RAMECC_CR_ECCELEN;
+
+ /* Disable all global interrupts */
+ ((RAMECC_TypeDef *)((uint32_t)hramecc->Instance & 0xFFFFFF00U))->IER &= \
+ ~(RAMECC_IER_GIE | RAMECC_IER_GECCSEIE | RAMECC_IER_GECCDEIE | RAMECC_IER_GECCDEBWIE);
+
+ /* Disable all interrupts monitor */
+ hramecc->Instance->CR &= ~(RAMECC_CR_ECCSEIE | RAMECC_CR_ECCDEIE | RAMECC_CR_ECCDEBWIE);
+
+ /* Clear RAMECC monitor flags */
+ __HAL_RAMECC_CLEAR_FLAG (hramecc, RAMECC_FLAGS_ALL);
+
+ /* Initialise the RAMECC error code */
+ hramecc->ErrorCode = HAL_RAMECC_ERROR_NONE;
+
+ /* Update the RAMECC state */
+ hramecc->State = HAL_RAMECC_STATE_READY;
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief DeInitializes the RAMECC peripheral.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_RAMECC_DeInit (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the RAMECC peripheral handle */
+ if (hramecc == NULL)
+ {
+ /* Return HAL status */
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Disable RAMECC monitor */
+ hramecc->Instance->CR &= ~RAMECC_CR_ECCELEN;
+
+ /* Disable all global interrupts */
+ ((RAMECC_TypeDef *)((uint32_t)hramecc->Instance & 0xFFFFFF00U))->IER &= \
+ ~(RAMECC_IER_GIE | RAMECC_IER_GECCSEIE | RAMECC_IER_GECCDEIE | RAMECC_IER_GECCDEBWIE);
+
+ /* Disable all interrupts monitor */
+ hramecc->Instance->CR &= ~(RAMECC_CR_ECCSEIE | RAMECC_CR_ECCDEIE | RAMECC_CR_ECCDEBWIE);
+
+ /* Clear RAMECC monitor flags */
+ __HAL_RAMECC_CLEAR_FLAG (hramecc, RAMECC_FLAGS_ALL);
+
+ /* Clean callback */
+ hramecc->DetectErrorCallback = NULL;
+
+ /* Initialise the RAMECC error code */
+ hramecc->ErrorCode = HAL_RAMECC_ERROR_NONE;
+
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_RESET;
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RAMECC_Exported_Functions_Group2
+ *
+@verbatim
+ ===============================================================================
+ ##### Monitoring operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure latching error informations.
+ (+) Configure RAMECC Global/Monitor interrupts.
+ (+) Register and Unregister RAMECC callbacks
+ (+) Handle RAMECC interrupt request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Starts the RAMECC latching error information.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_RAMECC_StartMonitor (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Check RAMECC state */
+ if (hramecc->State == HAL_RAMECC_STATE_READY)
+ {
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_BUSY;
+
+ /* Enable RAMECC monitor */
+ hramecc->Instance->CR |= RAMECC_CR_ECCELEN;
+
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_READY;
+ }
+ else
+ {
+ /* Update the error code */
+ hramecc->ErrorCode = HAL_RAMECC_ERROR_BUSY;
+
+ /* Return HAL status */
+ return HAL_ERROR;
+ }
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Stop the RAMECC latching error informations.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_RAMECC_StopMonitor (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Check RAMECC state */
+ if (hramecc->State == HAL_RAMECC_STATE_READY)
+ {
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_BUSY;
+
+ /* Disable RAMECC monitor */
+ hramecc->Instance->CR &= ~RAMECC_CR_ECCELEN;
+
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_READY;
+ }
+ else
+ {
+ /* Update the error code */
+ hramecc->ErrorCode = HAL_RAMECC_ERROR_BUSY;
+
+ /* Return HAL status */
+ return HAL_ERROR;
+ }
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Enable the RAMECC error interrupts.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that
+ * contains the configuration information for the
+ * specified RAMECC Monitor.
+ * @param Notifications Select the notification.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_RAMECC_EnableNotification (RAMECC_HandleTypeDef *hramecc, uint32_t Notifications)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+ assert_param (IS_RAMECC_INTERRUPT (Notifications));
+
+ /* Check RAMECC state */
+ if (hramecc->State == HAL_RAMECC_STATE_READY)
+ {
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_BUSY;
+
+ /* Enable RAMECC interrupts */
+ __HAL_RAMECC_ENABLE_IT (hramecc, Notifications);
+
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_READY;
+ }
+ else
+ {
+ /* Update the error code */
+ hramecc->ErrorCode = HAL_RAMECC_ERROR_BUSY;
+
+ /* Return HAL status */
+ return HAL_ERROR;
+ }
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Disable the RAMECC error interrupts.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that
+ * contains the configuration information for the
+ * specified RAMECC Monitor.
+ * @param Notifications Select the notification.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_RAMECC_DisableNotification (RAMECC_HandleTypeDef *hramecc, uint32_t Notifications)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+ assert_param (IS_RAMECC_INTERRUPT (Notifications));
+
+ /* Check RAMECC state */
+ if (hramecc->State == HAL_RAMECC_STATE_READY)
+ {
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_BUSY;
+
+ /* Disable RAMECC interrupts */
+ __HAL_RAMECC_DISABLE_IT (hramecc, Notifications);
+
+ /* Change RAMECC peripheral state */
+ hramecc->State = HAL_RAMECC_STATE_READY;
+ }
+ else
+ {
+ /* Update the error code */
+ hramecc->ErrorCode = HAL_RAMECC_ERROR_BUSY;
+
+ /* Return HAL status */
+ return HAL_ERROR;
+ }
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Register callbacks.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @param pCallback pointer to private callbacsk function which has pointer to
+ * a RAMECC_HandleTypeDef structure as parameter.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_RAMECC_RegisterCallback (RAMECC_HandleTypeDef *hramecc, void (* pCallback)(RAMECC_HandleTypeDef *_hramecc))
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hramecc->ErrorCode |= HAL_RAMECC_ERROR_INVALID_CALLBACK;
+
+ /* Return HAL status */
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Check RAMECC state */
+ if (hramecc->State == HAL_RAMECC_STATE_READY)
+ {
+ hramecc->DetectErrorCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hramecc->ErrorCode = HAL_RAMECC_ERROR_INVALID_CALLBACK;
+
+ /* Update HAL status */
+ status = HAL_ERROR;
+ }
+
+ /* Return HAL status */
+ return status;
+}
+
+
+/**
+ * @brief UnRegister callbacks.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_RAMECC_UnRegisterCallback (RAMECC_HandleTypeDef *hramecc)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Check RAMECC state */
+ if(hramecc->State == HAL_RAMECC_STATE_READY)
+ {
+ hramecc->DetectErrorCallback = NULL;
+ }
+ else
+ {
+ /* Update the error code */
+ hramecc->ErrorCode = HAL_RAMECC_ERROR_INVALID_CALLBACK;
+
+ /* Update HAL status */
+ status = HAL_ERROR;
+ }
+
+ /* Return HAL status */
+ return status;
+}
+
+
+/**
+ * @brief Handles RAMECC interrupt request.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval None.
+ */
+void HAL_RAMECC_IRQHandler (RAMECC_HandleTypeDef *hramecc)
+{
+ uint32_t ier_reg = ((RAMECC_TypeDef *)((uint32_t)hramecc->Instance & 0xFFFFFF00U))->IER;
+ uint32_t cr_reg = hramecc->Instance->CR >> 1U;
+ uint32_t sr_reg = hramecc->Instance->SR << 1U;
+
+ /* Update global interrupt variables */
+ if ((ier_reg & RAMECC_IER_GIE) == RAMECC_IER_GIE)
+ {
+ ier_reg = RAMECC_IT_GLOBAL_ALL;
+ }
+
+ /* Clear active flags */
+ __HAL_RAMECC_CLEAR_FLAG (hramecc, (((ier_reg | cr_reg) & sr_reg) >> 1U));
+
+ /* Check if a valid double error callback is registred */
+ if (hramecc->DetectErrorCallback != NULL)
+ {
+ /* Error detection callback */
+ hramecc->DetectErrorCallback(hramecc);
+ }
+}
+
+
+/** @addtogroup RAMECC_Exported_Functions_Group3
+ *
+@verbatim
+ ===============================================================================
+ ##### Error informations functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Get failing address.
+ (+) Get failing data low.
+ (+) Get failing data high.
+ (+) Get hamming bits injected.
+ (+) Check single error flag.
+ (+) Check double error flag.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the RAMECC failing address.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval Failing address offset.
+ */
+uint32_t HAL_RAMECC_GetFailingAddress (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Return failing address */
+ return hramecc->Instance->FAR;
+}
+
+
+/**
+ * @brief Return the RAMECC data low.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval Failing data low.
+ */
+uint32_t HAL_RAMECC_GetFailingDataLow (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Return failing data low */
+ return hramecc->Instance->FDRL;
+}
+
+
+/**
+ * @brief Return the RAMECC data high.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval Failing data high.
+ */
+uint32_t HAL_RAMECC_GetFailingDataHigh (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Return failing data high */
+ return hramecc->Instance->FDRH;
+}
+
+
+/**
+ * @brief Return the RAMECC Hamming bits injected.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval Hamming bits injected.
+ */
+uint32_t HAL_RAMECC_GetHammingErrorCode (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Return hamming bits injected */
+ return hramecc->Instance->FECR;
+}
+
+/**
+ * @brief Check if an ECC single error was occured.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval State of bit (1 or 0).
+ */
+uint32_t HAL_RAMECC_IsECCSingleErrorDetected (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Return the state of SEDC flag */
+ return ((READ_BIT(hramecc->Instance->SR, RAMECC_SR_SEDCF) == (RAMECC_SR_SEDCF)) ? 1UL : 0UL);
+}
+
+/**
+ * @brief Check if an ECC double error was occured.
+ * @param hramecc Pointer to a RAMECC_HandleTypeDef structure that contains
+ * the configuration information for the specified RAMECC
+ * Monitor.
+ * @retval State of bit (1 or 0).
+ */
+uint32_t HAL_RAMECC_IsECCDoubleErrorDetected (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Check the parameters */
+ assert_param (IS_RAMECC_MONITOR_ALL_INSTANCE (hramecc->Instance));
+
+ /* Return the state of DEDF | DEBWDF flags */
+ return ((READ_BIT(hramecc->Instance->SR, (RAMECC_SR_DEDF | RAMECC_SR_DEBWDF)) != 0U) ? 1UL : 0UL);
+}
+/**
+ * @}
+ */
+
+
+/** @addtogroup RAMECC_Exported_Functions_Group4
+ *
+@verbatim
+ ===============================================================================
+ ##### State and Error Functions #####
+ ===============================================================================
+ [..]
+ This section provides functions allowing to check and get the RAMECC state
+ and the error code .
+ [..]
+ The HAL_RAMECC_GetState() function allows to get the RAMECC peripheral
+ state.
+ The HAL_RAMECC_GetError() function allows to Get the RAMECC peripheral error
+ code.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Get the RAMECC peripheral state.
+ * @param hramecc : Pointer to a RAMECC_HandleTypeDef structure that
+ * contains the configuration information for the
+ * specified RAMECC instance.
+ * @retval RAMECC state.
+ */
+HAL_RAMECC_StateTypeDef HAL_RAMECC_GetState (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Return the RAMECC state */
+ return hramecc->State;
+}
+
+/**
+ * @brief Get the RAMECC peripheral error code.
+ * @param hramecc : Pointer to a RAMECC_HandleTypeDef structure that
+ * contains the configuration information for the
+ * specified RAMECC instance.
+ * @retval RAMECC error code.
+ */
+uint32_t HAL_RAMECC_GetError (RAMECC_HandleTypeDef *hramecc)
+{
+ /* Return the RAMECC error code */
+ return hramecc->ErrorCode;
+}
+/**
+ * @}
+ */
+#endif /* HAL_RAMECC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_rcc.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rcc.c
new file mode 100644
index 0000000000..7d73fa5772
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rcc.c
@@ -0,0 +1,1775 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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);
+
+ /* 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(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, just the calibration is allowed */
+ else
+ {
+ /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
+ __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
+ }
+ }
+
+ else
+ {
+ /* Check the HSI State */
+ if((RCC_OscInitStruct->HSIState)!= RCC_HSI_OFF)
+ {
+ /* Enable the Internal High Speed oscillator (HSI, 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_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;
+ }
+ }
+ }
+ 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(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_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 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_CCSCallback();
+
+ /* 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_CCSCallback(void)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_RCC_CCSCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RCC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_rcc_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rcc_ex.c
new file mode 100644
index 0000000000..fa08e6920b
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rcc_ex.c
@@ -0,0 +1,3437 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 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 function prototypes -----------------------------------------------*/
+static HAL_StatusTypeDef RCCEx_PLL2_Config(RCC_PLL2InitTypeDef *pll2, uint32_t Divider);
+static HAL_StatusTypeDef RCCEx_PLL3_Config(RCC_PLL3InitTypeDef *pll3, uint32_t Divider);
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup RCCEx_Exported_Functions 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, 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;
+
+ 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;
+
+ 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_PCLK1: /* CD/D2 PCLK1 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 Configuration ------------------------*/
+ 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);
+
+ }
+
+ /*------------------------------ 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(HRTIM)
+ /*------------------------------ 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 /*HRTIM*/
+ /*------------------------------ 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);
+ }
+
+ 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, 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;
+
+PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2C123;
+#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(HRTIM)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_HRTIM1;
+#endif /* HRTIM */
+#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();
+ /* Get the I2C1/2/3 clock source -------------------------------------------*/
+ PeriphClkInit->I2c123ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
+ /* Get the LPTIM1 clock source ---------------------------------------------*/
+ PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE();
+ /* Get the LPTIM2 clock source ---------------------------------------------*/
+ PeriphClkInit->Lptim2ClockSelection = __HAL_RCC_GET_LPTIM2_SOURCE();
+ /* Get the 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(uint32_t PeriphClk)
+{
+ PLL1_ClocksTypeDef pll1_clocks;
+ PLL2_ClocksTypeDef pll2_clocks;
+ PLL3_ClocksTypeDef pll3_clocks;
+
+ /* This variable is used to store the SAI 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 */
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ break;
+ }
+ case RCC_SAI1CLKSOURCE_PLL2: /* PLL2 is the clock source for SAI1 */
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ break;
+ }
+
+ case RCC_SAI1CLKSOURCE_PLL3: /* PLL3 is the clock source for SAI1 */
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ break;
+ }
+
+ case RCC_SAI1CLKSOURCE_CLKP: /* CKPER is the clock source for SAI1*/
+ {
+
+ ckpclocksource= __HAL_RCC_GET_CLKP_SOURCE();
+
+ if(ckpclocksource== RCC_CLKPSOURCE_HSI)
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = HSI_VALUE;
+ }
+
+ else if(ckpclocksource== RCC_CLKPSOURCE_CSI)
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if (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 0: /* PLL1 is the clock source for SAI2/3 */
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ break;
+ }
+ case RCC_SAI23CLKSOURCE_PLL2: /* PLL2 is the clock source for SAI2/3 */
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ break;
+ }
+
+ case RCC_SAI23CLKSOURCE_PLL3: /* PLL3 is the clock source for SAI2/3 */
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ break;
+ }
+
+ case RCC_SAI23CLKSOURCE_CLKP: /* CKPER is the clock source for SAI2/3 */
+ {
+
+ ckpclocksource= __HAL_RCC_GET_CLKP_SOURCE();
+
+ if(ckpclocksource== RCC_CLKPSOURCE_HSI)
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = HSI_VALUE;
+ }
+
+ else if(ckpclocksource== RCC_CLKPSOURCE_CSI)
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if (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 0: /* PLL1 is the clock source for SAI2A */
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ break;
+ }
+ case RCC_SAI2ACLKSOURCE_PLL2: /* PLLI2 is the clock source for SAI2A */
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ break;
+ }
+
+ case RCC_SAI2ACLKSOURCE_PLL3: /* PLLI3 is the clock source for SAI2A */
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ break;
+ }
+
+ case RCC_SAI2ACLKSOURCE_CLKP: /* CKPER is the clock source for SAI2A */
+ {
+
+ ckpclocksource= __HAL_RCC_GET_CLKP_SOURCE();
+
+ if(ckpclocksource== RCC_CLKPSOURCE_HSI)
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = HSI_VALUE;
+ }
+
+ else if(ckpclocksource== RCC_CLKPSOURCE_CSI)
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if (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 0: /* PLL1 is the clock source for SAI2B */
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ break;
+ }
+ case RCC_SAI2BCLKSOURCE_PLL2: /* PLLI2 is the clock source for SAI2B */
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ break;
+ }
+
+ case RCC_SAI2BCLKSOURCE_PLL3: /* PLLI3 is the clock source for SAI2B */
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ break;
+ }
+
+ case RCC_SAI2BCLKSOURCE_CLKP: /* CKPER is the clock source for SAI2B*/
+ {
+
+ ckpclocksource= __HAL_RCC_GET_CLKP_SOURCE();
+
+ if(ckpclocksource== RCC_CLKPSOURCE_HSI)
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = HSI_VALUE;
+ }
+
+ else if(ckpclocksource== RCC_CLKPSOURCE_CSI)
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if (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 0: /* PLL1 is the clock source for SAI4A */
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ break;
+ }
+ case RCC_D3CCIPR_SAI4ASEL_0: /* PLLI2 is the clock source for SAI4A */
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ break;
+ }
+
+ case RCC_D3CCIPR_SAI4ASEL_1: /* PLLI3 is the clock source for SAI4A */
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ break;
+ }
+
+ case RCC_D3CCIPR_SAI4ASEL_2: /* CKPER is the clock source for SAI4A*/
+ {
+
+ ckpclocksource= __HAL_RCC_GET_CLKP_SOURCE();
+
+ if(ckpclocksource== RCC_CLKPSOURCE_HSI)
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = HSI_VALUE;
+ }
+
+ else if(ckpclocksource== RCC_CLKPSOURCE_CSI)
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if (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_D3CCIPR_SAI4ASEL_0 | RCC_D3CCIPR_SAI4ASEL_1 ): /* 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 0: /* PLL1 is the clock source for SAI4B */
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ break;
+ }
+ case RCC_D3CCIPR_SAI4BSEL_0: /* PLLI2 is the clock source for SAI4B */
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ break;
+ }
+
+ case RCC_D3CCIPR_SAI4BSEL_1: /* PLLI3 is the clock source for SAI4B */
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ break;
+ }
+
+ case RCC_D3CCIPR_SAI4BSEL_2: /* CKPER is the clock source for SAI4B*/
+ {
+
+ ckpclocksource= __HAL_RCC_GET_CLKP_SOURCE();
+
+ if(ckpclocksource== RCC_CLKPSOURCE_HSI)
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = HSI_VALUE;
+ }
+
+ else if(ckpclocksource== RCC_CLKPSOURCE_CSI)
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if (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_D3CCIPR_SAI4BSEL_0 | RCC_D3CCIPR_SAI4BSEL_1 ): /* 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 I2S */
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ break;
+ }
+ case RCC_SPI123CLKSOURCE_PLL2: /* PLL2 is the clock source for I2S */
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ break;
+ }
+
+ case RCC_SPI123CLKSOURCE_PLL3: /* PLL3 is the clock source for I2S */
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ break;
+ }
+
+ case RCC_SPI123CLKSOURCE_CLKP: /* CKPER is the clock source for I2S */
+ {
+
+ ckpclocksource= __HAL_RCC_GET_CLKP_SOURCE();
+
+ if(ckpclocksource== RCC_CLKPSOURCE_HSI)
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = HSI_VALUE;
+ }
+
+ else if(ckpclocksource== RCC_CLKPSOURCE_CSI)
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if (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_ADC)
+ {
+ /* Get ADC clock source */
+ srcclk= __HAL_RCC_GET_ADC_SOURCE();
+
+ switch (srcclk)
+ {
+ case RCC_ADCCLKSOURCE_PLL2:
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ break;
+ }
+ case RCC_ADCCLKSOURCE_PLL3:
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_R_Frequency;
+ break;
+ }
+
+ case RCC_ADCCLKSOURCE_CLKP:
+ {
+
+ ckpclocksource= __HAL_RCC_GET_CLKP_SOURCE();
+
+ if(ckpclocksource== RCC_CLKPSOURCE_HSI)
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = HSI_VALUE;
+ }
+
+ else if(ckpclocksource== RCC_CLKPSOURCE_CSI)
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if (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 */
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ break;
+ }
+ case RCC_SDMMCCLKSOURCE_PLL2: /* PLL2 is the clock source for SDMMC */
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_R_Frequency;
+ 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 */
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_Q_Frequency;
+ break;
+ }
+ case RCC_SPI6CLKSOURCE_PLL3: /* PLL3 is the clock source for SPI6 */
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_Q_Frequency;
+ break;
+ }
+ case RCC_SPI6CLKSOURCE_HSI: /* HSI is the clock source for SPI6 */
+ {
+ frequency = HSI_VALUE;
+ break;
+ }
+ case RCC_SPI6CLKSOURCE_CSI: /* CSI is the clock source for SPI6 */
+ {
+ frequency = CSI_VALUE;
+ break;
+ }
+ case RCC_SPI6CLKSOURCE_HSE: /* HSE is the clock source for SPI6 */
+ {
+ frequency = HSE_VALUE;
+ 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
+ {
+ 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)CSI_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(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 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(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(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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_rng.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rng.c
new file mode 100644
index 0000000000..b4585ccb98
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rng.c
@@ -0,0 +1,927 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_rng.c
+ * @author MCD Application Team
+ * @brief RNG HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Random Number Generator (RNG) peripheral:
+ * + Initialization and configuration functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The RNG HAL driver can be used as follows:
+
+ (#) Enable the RNG controller clock using __HAL_RCC_RNG_CLK_ENABLE() macro
+ in HAL_RNG_MspInit().
+ (#) Activate the RNG peripheral using HAL_RNG_Init() function.
+ (#) Wait until the 32 bit Random Number Generator contains a valid
+ random data using (polling/interrupt) mode.
+ (#) Get the 32 bit random number using HAL_RNG_GenerateRandomNumber() function.
+
+ ##### Callback registration #####
+ ==================================
+
+ [..]
+ The compilation define USE_HAL_RNG_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ [..]
+ Use Function @ref HAL_RNG_RegisterCallback() to register a user callback.
+ Function @ref HAL_RNG_RegisterCallback() allows to register following callbacks:
+ (+) ErrorCallback : RNG Error Callback.
+ (+) MspInitCallback : RNG MspInit.
+ (+) MspDeInitCallback : RNG MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function @ref HAL_RNG_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function.
+ @ref HAL_RNG_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) ErrorCallback : RNG Error Callback.
+ (+) MspInitCallback : RNG MspInit.
+ (+) MspDeInitCallback : RNG MspDeInit.
+
+ [..]
+ For specific callback ReadyDataCallback, use dedicated register callbacks:
+ respectively @ref HAL_RNG_RegisterReadyDataCallback() , @ref HAL_RNG_UnRegisterReadyDataCallback().
+
+ [..]
+ By default, after the @ref HAL_RNG_Init() and when the state is HAL_RNG_STATE_RESET
+ all callbacks are set to the corresponding weak (surcharged) functions:
+ example @ref HAL_RNG_ErrorCallback().
+ Exception done for MspInit and MspDeInit functions that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_RNG_Init()
+ and @ref HAL_RNG_DeInit() only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_RNG_Init() and @ref HAL_RNG_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
+
+ [..]
+ Callbacks can be registered/unregistered in HAL_RNG_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_RNG_STATE_READY or HAL_RNG_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 @ref HAL_RNG_RegisterCallback() before calling @ref HAL_RNG_DeInit()
+ or @ref HAL_RNG_Init() function.
+
+ [..]
+ When The compilation define USE_HAL_RNG_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available
+ and weak (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#if defined (RNG)
+
+/** @addtogroup RNG
+ * @brief RNG HAL module driver.
+ * @{
+ */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup RNG_Private_Defines
+ * @{
+ */
+/* Health test control register information to use in CCM algorithm */
+#define RNG_HTCFG_1 0x17590ABCU /*!< magic number */
+#if defined(RNG_VER_3_1) || defined(RNG_VER_3_0)
+#define RNG_HTCFG 0x000CAA74U /*!< for best latency and To be compliant with NIST */
+#else /*RNG_VER_3_2*/
+#define RNG_HTCFG 0x00007274U /*!< for best latency and To be compliant with NIST */
+#endif
+/**
+ * @}
+ */
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @defgroup RNG_Private_Constants RNG Private Constants
+ * @{
+ */
+#define RNG_TIMEOUT_VALUE 2U
+/**
+ * @}
+ */
+/* Private macros ------------------------------------------------------------*/
+/* Private functions prototypes ----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup RNG_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup RNG_Exported_Functions_Group1
+ * @brief Initialization and configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the RNG according to the specified parameters
+ in the RNG_InitTypeDef and create the associated handle
+ (+) DeInitialize the RNG peripheral
+ (+) Initialize the RNG MSP
+ (+) DeInitialize RNG MSP
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the RNG peripheral and creates the associated handle.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng)
+{
+ uint32_t tickstart;
+ /* Check the RNG handle allocation */
+ if (hrng == NULL)
+ {
+ return HAL_ERROR;
+ }
+ /* Check the parameters */
+ assert_param(IS_RNG_ALL_INSTANCE(hrng->Instance));
+ assert_param(IS_RNG_CED(hrng->Init.ClockErrorDetection));
+
+#if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
+ if (hrng->State == HAL_RNG_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hrng->Lock = HAL_UNLOCKED;
+
+ hrng->ReadyDataCallback = HAL_RNG_ReadyDataCallback; /* Legacy weak ReadyDataCallback */
+ hrng->ErrorCallback = HAL_RNG_ErrorCallback; /* Legacy weak ErrorCallback */
+
+ if (hrng->MspInitCallback == NULL)
+ {
+ hrng->MspInitCallback = HAL_RNG_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware */
+ hrng->MspInitCallback(hrng);
+ }
+#else
+ if (hrng->State == HAL_RNG_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hrng->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware */
+ HAL_RNG_MspInit(hrng);
+ }
+#endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
+
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+#if defined(RNG_CR_CONDRST)
+ /* Disable RNG */
+ __HAL_RNG_DISABLE(hrng);
+
+ /* Clock Error Detection Configuration when CONDRT bit is set to 1 */
+ MODIFY_REG(hrng->Instance->CR, RNG_CR_CED | RNG_CR_CONDRST, hrng->Init.ClockErrorDetection | RNG_CR_CONDRST);
+
+#if defined(RNG_VER_3_2) || defined(RNG_VER_3_1) || defined(RNG_VER_3_0)
+ /*!< magic number must be written immediately before to RNG_HTCRG */
+ WRITE_REG(hrng->Instance->HTCR, RNG_HTCFG_1);
+ /* for best latency and to be compliant with NIST */
+ WRITE_REG(hrng->Instance->HTCR, RNG_HTCFG);
+#endif
+
+ /* Writing bits CONDRST=0*/
+ CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait for conditioning reset process to be completed */
+ while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
+ {
+ if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
+ {
+ hrng->State = HAL_RNG_STATE_READY;
+ hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
+ return HAL_ERROR;
+ }
+ }
+#else
+ /* Clock Error Detection Configuration */
+ MODIFY_REG(hrng->Instance->CR, RNG_CR_CED, hrng->Init.ClockErrorDetection);
+#endif /* end of RNG_CR_CONDRST */
+
+ /* Enable the RNG Peripheral */
+ __HAL_RNG_ENABLE(hrng);
+
+ /* verify that no seed error */
+ if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
+ {
+ hrng->State = HAL_RNG_STATE_ERROR;
+ return HAL_ERROR;
+ }
+ /* Get tick */
+ tickstart = HAL_GetTick();
+ /* Check if data register contains valid random data */
+ while (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) != RESET)
+ {
+ if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
+ {
+ hrng->State = HAL_RNG_STATE_ERROR;
+ hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
+ return HAL_ERROR;
+ }
+ }
+
+ /* Initialize the RNG state */
+ hrng->State = HAL_RNG_STATE_READY;
+
+ /* Initialise the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_NONE;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the RNG peripheral.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_DeInit(RNG_HandleTypeDef *hrng)
+{
+#if defined(RNG_CR_CONDRST)
+ uint32_t tickstart;
+
+#endif /* RNG_CR_CONDRST */
+ /* Check the RNG handle allocation */
+ if (hrng == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+#if defined(RNG_CR_CONDRST)
+ /* Clear Clock Error Detection bit when CONDRT bit is set to 1 */
+ MODIFY_REG(hrng->Instance->CR, RNG_CR_CED | RNG_CR_CONDRST, RNG_CED_ENABLE | RNG_CR_CONDRST);
+
+ /* Writing bits CONDRST=0*/
+ CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait for conditioning reset process to be completed */
+ while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
+ {
+ if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
+ {
+ hrng->State = HAL_RNG_STATE_READY;
+ hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrng);
+ return HAL_ERROR;
+ }
+ }
+
+#else
+ /* Clear Clock Error Detection bit */
+ CLEAR_BIT(hrng->Instance->CR, RNG_CR_CED);
+#endif /* RNG_CR_CONDRST */
+ /* Disable the RNG Peripheral */
+ CLEAR_BIT(hrng->Instance->CR, RNG_CR_IE | RNG_CR_RNGEN);
+
+ /* Clear RNG interrupt status flags */
+ CLEAR_BIT(hrng->Instance->SR, RNG_SR_CEIS | RNG_SR_SEIS);
+
+#if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
+ if (hrng->MspDeInitCallback == NULL)
+ {
+ hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware */
+ hrng->MspDeInitCallback(hrng);
+#else
+ /* DeInit the low level hardware */
+ HAL_RNG_MspDeInit(hrng);
+#endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
+
+ /* Update the RNG state */
+ hrng->State = HAL_RNG_STATE_RESET;
+
+ /* Initialise the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_NONE;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrng);
+
+ /* Return the function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the RNG MSP.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval None
+ */
+__weak void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrng);
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_RNG_MspInit must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief DeInitializes the RNG MSP.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval None
+ */
+__weak void HAL_RNG_MspDeInit(RNG_HandleTypeDef *hrng)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrng);
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_RNG_MspDeInit must be implemented in the user file.
+ */
+}
+
+#if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User RNG Callback
+ * To be used instead of the weak predefined callback
+ * @param hrng RNG handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_RNG_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_RNG_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_RNG_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_RegisterCallback(RNG_HandleTypeDef *hrng, HAL_RNG_CallbackIDTypeDef CallbackID, pRNG_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hrng);
+
+ if (HAL_RNG_STATE_READY == hrng->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RNG_ERROR_CB_ID :
+ hrng->ErrorCallback = pCallback;
+ break;
+
+ case HAL_RNG_MSPINIT_CB_ID :
+ hrng->MspInitCallback = pCallback;
+ break;
+
+ case HAL_RNG_MSPDEINIT_CB_ID :
+ hrng->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_RNG_STATE_RESET == hrng->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RNG_MSPINIT_CB_ID :
+ hrng->MspInitCallback = pCallback;
+ break;
+
+ case HAL_RNG_MSPDEINIT_CB_ID :
+ hrng->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrng);
+ return status;
+}
+
+/**
+ * @brief Unregister an RNG Callback
+ * RNG callabck is redirected to the weak predefined callback
+ * @param hrng RNG handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_RNG_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_RNG_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_RNG_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_UnRegisterCallback(RNG_HandleTypeDef *hrng, HAL_RNG_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hrng);
+
+ if (HAL_RNG_STATE_READY == hrng->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RNG_ERROR_CB_ID :
+ hrng->ErrorCallback = HAL_RNG_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_RNG_MSPINIT_CB_ID :
+ hrng->MspInitCallback = HAL_RNG_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_RNG_MSPDEINIT_CB_ID :
+ hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_RNG_STATE_RESET == hrng->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RNG_MSPINIT_CB_ID :
+ hrng->MspInitCallback = HAL_RNG_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_RNG_MSPDEINIT_CB_ID :
+ hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrng);
+ return status;
+}
+
+/**
+ * @brief Register Data Ready RNG Callback
+ * To be used instead of the weak HAL_RNG_ReadyDataCallback() predefined callback
+ * @param hrng RNG handle
+ * @param pCallback pointer to the Data Ready Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_RegisterReadyDataCallback(RNG_HandleTypeDef *hrng, pRNG_ReadyDataCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hrng);
+
+ if (HAL_RNG_STATE_READY == hrng->State)
+ {
+ hrng->ReadyDataCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrng);
+ return status;
+}
+
+/**
+ * @brief UnRegister the Data Ready RNG Callback
+ * Data Ready RNG Callback is redirected to the weak HAL_RNG_ReadyDataCallback() predefined callback
+ * @param hrng RNG handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_UnRegisterReadyDataCallback(RNG_HandleTypeDef *hrng)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hrng);
+
+ if (HAL_RNG_STATE_READY == hrng->State)
+ {
+ hrng->ReadyDataCallback = HAL_RNG_ReadyDataCallback; /* Legacy weak ReadyDataCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrng);
+ return status;
+}
+
+#endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RNG_Exported_Functions_Group2
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Get the 32 bit Random number
+ (+) Get the 32 bit Random number with interrupt enabled
+ (+) Handle RNG interrupt request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Generates a 32-bit random number.
+ * @note This function checks value of RNG_FLAG_DRDY flag to know if valid
+ * random number is available in the DR register (RNG_FLAG_DRDY flag set
+ * whenever a random number is available through the RNG_DR register).
+ * After transitioning from 0 to 1 (random number available),
+ * RNG_FLAG_DRDY flag remains high until output buffer becomes empty after reading
+ * four words from the RNG_DR register, i.e. further function calls
+ * will immediately return a new u32 random number (additional words are
+ * available and can be read by the application, till RNG_FLAG_DRDY flag remains high).
+ * @note When no more random number data is available in DR register, RNG_FLAG_DRDY
+ * flag is automatically cleared.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @param random32bit pointer to generated random number variable if successful.
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hrng);
+
+ /* Check RNG peripheral state */
+ if (hrng->State == HAL_RNG_STATE_READY)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check if data register contains valid random data */
+ while (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET)
+ {
+ if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
+ {
+ hrng->State = HAL_RNG_STATE_READY;
+ hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrng);
+ return HAL_ERROR;
+ }
+ }
+
+ /* Get a 32bit Random number */
+ hrng->RandomNumber = hrng->Instance->DR;
+ *random32bit = hrng->RandomNumber;
+
+ hrng->State = HAL_RNG_STATE_READY;
+ }
+ else
+ {
+ hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrng);
+
+ return status;
+}
+
+/**
+ * @brief Generates a 32-bit random number in interrupt mode.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef *hrng)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hrng);
+
+ /* Check RNG peripheral state */
+ if (hrng->State == HAL_RNG_STATE_READY)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+ /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */
+ __HAL_RNG_ENABLE_IT(hrng);
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrng);
+
+ hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Handles RNG interrupt request.
+ * @note In the case of a clock error, the RNG is no more able to generate
+ * random numbers because the PLL48CLK clock is not correct. User has
+ * to check that the clock controller is correctly configured to provide
+ * the RNG clock and clear the CEIS bit using __HAL_RNG_CLEAR_IT().
+ * The clock error has no impact on the previously generated
+ * random numbers, and the RNG_DR register contents can be used.
+ * @note In the case of a seed error, the generation of random numbers is
+ * interrupted as long as the SECS bit is '1'. If a number is
+ * available in the RNG_DR register, it must not be used because it may
+ * not have enough entropy. In this case, it is recommended to clear the
+ * SEIS bit using __HAL_RNG_CLEAR_IT(), then disable and enable
+ * the RNG peripheral to reinitialize and restart the RNG.
+ * @note User-written HAL_RNG_ErrorCallback() API is called once whether SEIS
+ * or CEIS are set.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval None
+
+ */
+void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng)
+{
+ uint32_t rngclockerror = 0U;
+
+ /* RNG clock error interrupt occurred */
+ if (__HAL_RNG_GET_IT(hrng, RNG_IT_CEI) != RESET)
+ {
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_CLOCK;
+ rngclockerror = 1U;
+ }
+ else if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
+ {
+ /* Update the error code */
+ hrng->ErrorCode = HAL_RNG_ERROR_SEED;
+ rngclockerror = 1U;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if (rngclockerror == 1U)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_ERROR;
+
+#if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
+ /* Call registered Error callback */
+ hrng->ErrorCallback(hrng);
+#else
+ /* Call legacy weak Error callback */
+ HAL_RNG_ErrorCallback(hrng);
+#endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
+
+ /* Clear the clock error flag */
+ __HAL_RNG_CLEAR_IT(hrng, RNG_IT_CEI | RNG_IT_SEI);
+ }
+
+ /* Check RNG data ready interrupt occurred */
+ if (__HAL_RNG_GET_IT(hrng, RNG_IT_DRDY) != RESET)
+ {
+ /* Generate random number once, so disable the IT */
+ __HAL_RNG_DISABLE_IT(hrng);
+
+ /* Get the 32bit Random number (DRDY flag automatically cleared) */
+ hrng->RandomNumber = hrng->Instance->DR;
+
+ if (hrng->State != HAL_RNG_STATE_ERROR)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrng);
+
+#if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
+ /* Call registered Data Ready callback */
+ hrng->ReadyDataCallback(hrng, hrng->RandomNumber);
+#else
+ /* Call legacy weak Data Ready callback */
+ HAL_RNG_ReadyDataCallback(hrng, hrng->RandomNumber);
+#endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @brief Read latest generated random number.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval random value
+ */
+uint32_t HAL_RNG_ReadLastRandomNumber(RNG_HandleTypeDef *hrng)
+{
+ return (hrng->RandomNumber);
+}
+
+/**
+ * @brief Data Ready callback in non-blocking mode.
+ * @note When RNG_FLAG_DRDY flag value is set, first random number has been read
+ * from DR register in IRQ Handler and is provided as callback parameter.
+ * Depending on valid data available in the conditioning output buffer,
+ * additional words can be read by the application from DR register till
+ * DRDY bit remains high.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @param random32bit generated random number.
+ * @retval None
+ */
+__weak void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrng);
+ UNUSED(random32bit);
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_RNG_ReadyDataCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief RNG error callbacks.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval None
+ */
+__weak void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrng);
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_RNG_ErrorCallback must be implemented in the user file.
+ */
+}
+/**
+ * @}
+ */
+
+
+/** @addtogroup RNG_Exported_Functions_Group3
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the RNG state.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval HAL state
+ */
+HAL_RNG_StateTypeDef HAL_RNG_GetState(RNG_HandleTypeDef *hrng)
+{
+ return hrng->State;
+}
+
+/**
+ * @brief Return the RNG handle error code.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval RNG Error Code
+*/
+uint32_t HAL_RNG_GetError(RNG_HandleTypeDef *hrng)
+{
+ /* Return RNG Error Code */
+ return hrng->ErrorCode;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+#endif /* HAL_RNG_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+#endif /* RNG */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_rng_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rng_ex.c
new file mode 100644
index 0000000000..c71504ffa0
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rng_ex.c
@@ -0,0 +1,299 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_rng_ex.c
+ * @author MCD Application Team
+ * @brief Extended RNG HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Random Number Generator (RNG) peripheral:
+ * + Lock configuration functions
+ * + Reset the RNG
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#if defined (RNG)
+
+/** @addtogroup RNGEx
+ * @brief RNG Extended HAL module driver.
+ * @{
+ */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+#if defined (RNG_CR_CONDRST)
+/* Private types -------------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup RNGEx_Private_Defines
+ * @{
+ */
+/* Health test control register information to use in CCM algorithm */
+#define RNG_HTCFG_1 0x17590ABCU /*!< magic number */
+#if defined(RNG_VER_3_1) || defined(RNG_VER_3_0)
+#define RNG_HTCFG 0x000CAA74U /*!< for best latency and To be compliant with NIST */
+#else /*RNG_VER_3_2*/
+#define RNG_HTCFG 0x00007274U /*!< for best latency and To be compliant with NIST */
+#endif
+/**
+ * @}
+ */
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @defgroup RNGEx_Private_Constants RNG Private Constants
+ * @{
+ */
+#define RNG_TIMEOUT_VALUE 2U
+/**
+ * @}
+ */
+/* Private macros ------------------------------------------------------------*/
+/* Private functions prototypes ----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup RNGEx_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup RNGEx_Exported_Functions_Group1
+ * @brief Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Configuration and lock functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure the RNG with the specified parameters in the RNG_ConfigTypeDef
+ (+) Lock RNG configuration Allows user to lock a configuration until next reset.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the RNG with the specified parameters in the
+ * RNG_ConfigTypeDef.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @param pConf: pointer to a RNG_ConfigTypeDef structure that contains
+ * the configuration information for RNG module
+
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_RNGEx_SetConfig(RNG_HandleTypeDef *hrng, RNG_ConfigTypeDef *pConf)
+{
+ uint32_t tickstart;
+ uint32_t cr_value;
+ HAL_StatusTypeDef status ;
+
+ /* Check the RNG handle allocation */
+ if ((hrng == NULL) || (pConf == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_RNG_ALL_INSTANCE(hrng->Instance));
+ assert_param(IS_RNG_CLOCK_DIVIDER(pConf->ClockDivider));
+ assert_param(IS_RNG_NIST_COMPLIANCE(pConf->NistCompliance));
+ assert_param(IS_RNG_CONFIG1(pConf->Config1));
+ assert_param(IS_RNG_CONFIG2(pConf->Config2));
+ assert_param(IS_RNG_CONFIG3(pConf->Config3));
+
+ /* Check RNG peripheral state */
+ if (hrng->State == HAL_RNG_STATE_READY)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+ /* Disable RNG */
+ __HAL_RNG_DISABLE(hrng);
+
+ /* RNG CR register configuration. Set value in CR register for :
+ - NIST Compliance setting
+ - Clock divider value
+ - CONFIG 1, CONFIG 2 and CONFIG 3 values */
+
+ cr_value = (uint32_t)(pConf->ClockDivider | pConf->NistCompliance
+ | (pConf->Config1 << RNG_CR_RNG_CONFIG1_Pos)
+ | (pConf->Config2 << RNG_CR_RNG_CONFIG2_Pos)
+ | (pConf->Config3 << RNG_CR_RNG_CONFIG3_Pos));
+
+ MODIFY_REG(hrng->Instance->CR, RNG_CR_NISTC | RNG_CR_CLKDIV | RNG_CR_RNG_CONFIG1
+ | RNG_CR_RNG_CONFIG2 | RNG_CR_RNG_CONFIG3,
+ (uint32_t)(RNG_CR_CONDRST | cr_value));
+
+#if defined(RNG_VER_3_2) || defined(RNG_VER_3_1) || defined(RNG_VER_3_0)
+ /*!< magic number must be written immediately before to RNG_HTCRG */
+ WRITE_REG(hrng->Instance->HTCR, RNG_HTCFG_1);
+ /* for best latency and to be compliant with NIST */
+ WRITE_REG(hrng->Instance->HTCR, RNG_HTCFG);
+#endif
+
+ /* Writing bits CONDRST=0*/
+ CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait for conditioning reset process to be completed */
+ while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
+ {
+ if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
+ {
+ hrng->State = HAL_RNG_STATE_READY;
+ hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
+ return HAL_ERROR;
+ }
+ }
+
+ /* Enable RNG */
+ __HAL_RNG_ENABLE(hrng);
+
+ /* Initialize the RNG state */
+ hrng->State = HAL_RNG_STATE_READY;
+
+ /* function status */
+ status = HAL_OK;
+ }
+ else
+ {
+ hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Return the function status */
+ return status;
+}
+
+/**
+ * @brief Get the RNG Configuration and fill parameters in the
+ * RNG_ConfigTypeDef.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @param pConf: pointer to a RNG_ConfigTypeDef structure that contains
+ * the configuration information for RNG module
+
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_RNGEx_GetConfig(RNG_HandleTypeDef *hrng, RNG_ConfigTypeDef *pConf)
+{
+
+ HAL_StatusTypeDef status ;
+
+ /* Check the RNG handle allocation */
+ if ((hrng == NULL) || (pConf == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check RNG peripheral state */
+ if (hrng->State == HAL_RNG_STATE_READY)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+ /* Get RNG parameters */
+ pConf->Config1 = (uint32_t)((hrng->Instance->CR & RNG_CR_RNG_CONFIG1) >> RNG_CR_RNG_CONFIG1_Pos) ;
+ pConf->Config2 = (uint32_t)((hrng->Instance->CR & RNG_CR_RNG_CONFIG2) >> RNG_CR_RNG_CONFIG2_Pos);
+ pConf->Config3 = (uint32_t)((hrng->Instance->CR & RNG_CR_RNG_CONFIG3) >> RNG_CR_RNG_CONFIG3_Pos);
+ pConf->ClockDivider = (hrng->Instance->CR & RNG_CR_CLKDIV);
+ pConf->NistCompliance = (hrng->Instance->CR & RNG_CR_NISTC);
+
+ /* Initialize the RNG state */
+ hrng->State = HAL_RNG_STATE_READY;
+
+ /* function status */
+ status = HAL_OK;
+ }
+ else
+ {
+ hrng->ErrorCode |= HAL_RNG_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Return the function status */
+ return status;
+}
+
+/**
+ * @brief RNG current configuration lock.
+ * @note This function allows to lock RNG peripheral configuration.
+ * Once locked, HW RNG reset has to be perfomed prior any further
+ * configuration update.
+ * @param hrng pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_RNGEx_LockConfig(RNG_HandleTypeDef *hrng)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the RNG handle allocation */
+ if (hrng == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check RNG peripheral state */
+ if (hrng->State == HAL_RNG_STATE_READY)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+ /* Perform RNG configuration Lock */
+ MODIFY_REG(hrng->Instance->CR, RNG_CR_CONFIGLOCK, RNG_CR_CONFIGLOCK);
+
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_READY;
+
+ /* function status */
+ status = HAL_OK;
+ }
+ else
+ {
+ hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
+ status = HAL_ERROR;
+ }
+
+ /* Return the function status */
+ return status;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* CONDRST */
+#endif /* HAL_RNG_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+#endif /* RNG */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_rtc.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rtc.c
new file mode 100644
index 0000000000..b458a92169
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rtc.c
@@ -0,0 +1,2144 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_rtc.c
+ * @author MCD Application Team
+ * @brief RTC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Real-Time Clock (RTC) peripheral:
+ * + Initialization/de-initialization
+ * + Calendar (Time and Date) configuration
+ * + Alarms (Alarm A and Alarm B) configuration
+ * + WakeUp Timer configuration
+ * + TimeStamp configuration
+ * + Tampers configuration
+ * + Backup Data Registers configuration
+ * + RTC Tamper and TimeStamp Pins Selection
+ * + Interrupts and flags management
+ *
+ @verbatim
+ ===============================================================================
+ ##### RTC Operating Condition #####
+ ===============================================================================
+ [..] The real-time clock (RTC) and the RTC backup registers can be powered
+ from the VBAT voltage when the main VDD supply is powered off.
+ To retain the content of the RTC backup registers and supply the RTC
+ when VDD is turned off, VBAT pin can be connected to an optional
+ standby voltage supplied by a battery or by another source.
+
+ ##### Backup Domain Reset #####
+ ===============================================================================
+ [..] The backup domain reset sets all RTC registers and the RCC_BDCR register
+ to their reset values.
+ A backup domain reset is generated when one of the following events occurs:
+ (#) Software reset, triggered by setting the BDRST bit in the
+ RCC Backup domain control register (RCC_BDCR).
+ (#) VDD or VBAT power on, if both supplies have previously been powered off.
+ (#) Tamper detection event resets all data backup registers.
+
+ ##### Backup Domain Access #####
+ ===================================================================
+ [..] After reset, the backup domain (RTC registers, RTC backup data
+ registers and backup SRAM) is protected against possible unwanted write
+ accesses.
+
+ [..] To enable access to the RTC Domain and RTC registers, proceed as follows:
+ (#) Call the function HAL_RCCEx_PeriphCLKConfig with RCC_PERIPHCLK_RTC for
+ PeriphClockSelection and select RTCClockSelection (LSE, LSI or HSEdiv32)
+ (#) Enable RTC Clock using the __HAL_RCC_RTC_ENABLE() macro.
+
+ ##### How to use RTC Driver #####
+ ===================================================================
+ [..]
+ (+) Enable the RTC domain access (see description in the section above).
+ (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour
+ format using the HAL_RTC_Init() function.
+
+ *** Time and Date configuration ***
+ ===================================
+ [..]
+ (+) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime()
+ and HAL_RTC_SetDate() functions.
+ (+) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate() functions.
+
+ *** Alarm configuration ***
+ ===========================
+ [..]
+ (+) To configure the RTC Alarm use the HAL_RTC_SetAlarm() function.
+ You can also configure the RTC Alarm with interrupt mode using the
+ HAL_RTC_SetAlarm_IT() function.
+ (+) To read the RTC Alarm, use the HAL_RTC_GetAlarm() function.
+
+ ##### RTC and low power modes #####
+ ===================================================================
+ [..] The MCU can be woken up from a low power mode by an RTC alternate
+ function.
+ [..] The RTC alternate functions are the RTC alarms (Alarm A and Alarm B),
+ RTC wakeup, RTC tamper event detection and RTC time stamp event detection.
+ These RTC alternate functions can wake up the system from the Stop and
+ Standby low power modes.
+ [..] The system can also wake up from low power modes without depending
+ on an external interrupt (Auto-wakeup mode), by using the RTC alarm
+ or the RTC wakeup events.
+ [..] The RTC provides a programmable time base for waking up from the
+ Stop or Standby mode at regular intervals.
+ Wakeup from STOP and STANDBY modes is possible only when the RTC clock source
+ is LSE or LSI.
+
+ *** Callback registration ***
+ =============================================
+ When The compilation define USE_HAL_RTC_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available and all callbacks
+ are set to the corresponding weak functions. This is the recommended configuration
+ in order to optimize memory/code consumption footprint/performances.
+
+ The compilation define USE_RTC_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Function @ref HAL_RTC_RegisterCallback() to register an interrupt callback.
+
+ Function @ref HAL_RTC_RegisterCallback() allows to register following callbacks:
+ (+) AlarmAEventCallback : RTC Alarm A Event callback.
+ (+) AlarmBEventCallback : RTC Alarm B Event callback.
+ (+) TimeStampEventCallback : RTC TimeStamp Event callback.
+ (+) WakeUpTimerEventCallback : RTC WakeUpTimer Event callback.
+ (+) Tamper1EventCallback : RTC Tamper 1 Event callback.
+ (+) Tamper2EventCallback : RTC Tamper 2 Event callback.
+ (+) Tamper3EventCallback : RTC Tamper 3 Event callback.
+ (+) MspInitCallback : RTC MspInit callback.
+ (+) MspDeInitCallback : RTC MspDeInit callback.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function @ref HAL_RTC_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ @ref HAL_RTC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) AlarmAEventCallback : RTC Alarm A Event callback.
+ (+) AlarmBEventCallback : RTC Alarm B Event callback.
+ (+) TimeStampEventCallback : RTC TimeStamp Event callback.
+ (+) WakeUpTimerEventCallback : RTC WakeUpTimer Event callback.
+ (+) Tamper1EventCallback : RTC Tamper 1 Event callback.
+ (+) Tamper2EventCallback : RTC Tamper 2 Event callback.
+ (+) Tamper3EventCallback : RTC Tamper 3 Event callback.
+ (+) MspInitCallback : RTC MspInit callback.
+ (+) MspDeInitCallback : RTC MspDeInit callback.
+
+ By default, after the @ref HAL_RTC_Init() and when the state is HAL_RTC_STATE_RESET,
+ all callbacks are set to the corresponding weak functions :
+ examples @ref AlarmAEventCallback(), @ref WakeUpTimerEventCallback().
+ Exception done for MspInit and MspDeInit callbacks that are reset to the legacy weak function
+ in the @ref HAL_RTC_Init()/@ref HAL_RTC_DeInit() only when these callbacks are null
+ (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, @ref HAL_RTC_Init()/@ref HAL_RTC_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in HAL_RTC_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_RTC_STATE_READY or HAL_RTC_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 @ref HAL_RTC_RegisterCallback() before calling @ref HAL_RTC_DeInit()
+ or @ref HAL_RTC_Init() function.
+
+ When The compilation define USE_HAL_RTC_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available and all callbacks
+ are set to the corresponding weak functions.
+ @endverbatim
+
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+
+/** @addtogroup RTC
+ * @brief RTC HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup RTC_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup RTC_Exported_Functions_Group1
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to initialize and configure the
+ RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable
+ RTC registers Write protection, enter and exit the RTC initialization mode,
+ RTC registers synchronization check and reference clock detection enable.
+ (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base.
+ It is split into 2 programmable prescalers to minimize power consumption.
+ (++) A 7-bit asynchronous prescaler and a 15-bit synchronous prescaler.
+ (++) When both prescalers are used, it is recommended to configure the
+ asynchronous prescaler to a high value to minimize power consumption.
+ (#) All RTC registers are Write protected. Writing to the RTC registers
+ is enabled by writing a key into the Write Protection register, RTC_WPR.
+ (#) To configure the RTC Calendar, user application should enter
+ initialization mode. In this mode, the calendar counter is stopped
+ and its value can be updated. When the initialization sequence is
+ complete, the calendar restarts counting after 4 RTCCLK cycles.
+ (#) To read the calendar through the shadow registers after Calendar
+ initialization, calendar update or after wakeup from low power modes
+ the software must first clear the RSF flag. The software must then
+ wait until it is set again before reading the calendar, which means
+ that the calendar registers have been correctly copied into the
+ RTC_TR and RTC_DR shadow registers.The HAL_RTC_WaitForSynchro() function
+ implements the above software sequence (RSF clear and RSF check).
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the RTC peripheral
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Check RTC handler */
+ if(hrtc != NULL)
+ {
+ status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
+ assert_param(IS_RTC_HOUR_FORMAT(hrtc->Init.HourFormat));
+ assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv));
+ assert_param(IS_RTC_SYNCH_PREDIV(hrtc->Init.SynchPrediv));
+ assert_param(IS_RTC_OUTPUT(hrtc->Init.OutPut));
+ assert_param(IS_RTC_OUTPUT_REMAP(hrtc->Init.OutPutRemap));
+ assert_param(IS_RTC_OUTPUT_POL(hrtc->Init.OutPutPolarity));
+ assert_param(IS_RTC_OUTPUT_TYPE(hrtc->Init.OutPutType));
+#if defined(RTC_CR_TAMPALRM_PU)
+ assert_param(IS_RTC_OUTPUT_PULLUP(hrtc->Init.OutPutPullUp));
+#endif /* RTC_CR_TAMPALRM_PU */
+
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ if(hrtc->State == HAL_RTC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hrtc->Lock = HAL_UNLOCKED;
+
+ hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */
+ hrtc->AlarmBEventCallback = HAL_RTCEx_AlarmBEventCallback; /* Legacy weak AlarmBEventCallback */
+ hrtc->TimeStampEventCallback = HAL_RTCEx_TimeStampEventCallback; /* Legacy weak TimeStampEventCallback */
+ hrtc->WakeUpTimerEventCallback = HAL_RTCEx_WakeUpTimerEventCallback; /* Legacy weak WakeUpTimerEventCallback */
+ hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */
+ hrtc->Tamper2EventCallback = HAL_RTCEx_Tamper2EventCallback; /* Legacy weak Tamper2EventCallback */
+ hrtc->Tamper3EventCallback = HAL_RTCEx_Tamper3EventCallback; /* Legacy weak Tamper3EventCallback */
+
+#if defined(TAMP_CR1_ITAMP1E)
+ hrtc->InternalTamper1EventCallback = HAL_RTCEx_InternalTamper1EventCallback;
+#endif /* TAMP_CR1_ITAMP1E */
+#if defined(TAMP_CR1_ITAMP2E)
+ hrtc->InternalTamper2EventCallback = HAL_RTCEx_InternalTamper2EventCallback;
+#endif /* TAMP_CR1_ITAMP2E */
+#if defined(TAMP_CR1_ITAMP3E)
+ hrtc->InternalTamper3EventCallback = HAL_RTCEx_InternalTamper3EventCallback;
+#endif /* TAMP_CR1_ITAMP3E */
+#if defined(TAMP_CR1_ITAMP4E)
+ hrtc->InternalTamper4EventCallback = HAL_RTCEx_InternalTamper4EventCallback;
+#endif /* TAMP_CR1_ITAMP4E */
+#if defined(TAMP_CR1_ITAMP5E)
+ hrtc->InternalTamper5EventCallback = HAL_RTCEx_InternalTamper5EventCallback;
+#endif /* TAMP_CR1_ITAMP5E */
+#if defined(TAMP_CR1_ITAMP6E)
+ hrtc->InternalTamper6EventCallback = HAL_RTCEx_InternalTamper6EventCallback;
+#endif /* TAMP_CR1_ITAMP6E */
+#if defined(TAMP_CR1_ITAMP8E)
+ hrtc->InternalTamper8EventCallback = HAL_RTCEx_InternalTamper8EventCallback;
+#endif /* TAMP_CR1_ITAMP8E */
+
+
+ if(hrtc->MspInitCallback == NULL)
+ {
+ hrtc->MspInitCallback = HAL_RTC_MspInit;
+ }
+ /* Init the low level hardware */
+ hrtc->MspInitCallback(hrtc);
+
+ if(hrtc->MspDeInitCallback == NULL)
+ {
+ hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
+ }
+ }
+#else /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ if(hrtc->State == HAL_RTC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hrtc->Lock = HAL_UNLOCKED;
+
+ /* Initialize RTC MSP */
+ HAL_RTC_MspInit(hrtc);
+ }
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ status = HAL_ERROR;
+ }
+ else
+ {
+#if defined(RTC_CR_TAMPOE)
+ /* Clear RTC_CR FMT, OSEL, POL and TAMPOE Bits */
+ hrtc->Instance->CR &= ~(RTC_CR_FMT | RTC_CR_POL | RTC_CR_OSEL | RTC_CR_TAMPOE);
+#else /* RTC_CR_TAMPOE */
+ /* Clear RTC_CR FMT, OSEL and POL Bits */
+ hrtc->Instance->CR &= ~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL);
+#endif /* RTC_CR_TAMPOE */
+
+ /* Set RTC_CR register */
+ hrtc->Instance->CR |= (hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity);
+
+ /* Configure the RTC PRER */
+ hrtc->Instance->PRER = (hrtc->Init.AsynchPrediv << RTC_PRER_PREDIV_A_Pos) | (hrtc->Init.SynchPrediv << RTC_PRER_PREDIV_S_Pos);
+
+ /* Exit Initialization mode */
+#if defined(RTC_ICSR_INIT)
+ CLEAR_BIT(hrtc->Instance->ICSR, RTC_ICSR_INIT);
+#endif /* RTC_ICSR_INIT */
+#if defined(RTC_ISR_INIT)
+ CLEAR_BIT(hrtc->Instance->ISR, RTC_ISR_INIT);
+#endif /* RTC_ISR_INIT */
+
+ /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == 0U)
+ {
+ if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+ status = HAL_ERROR;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+#if defined(RTC_CR_TAMPALRM_PU) && defined(RTC_CR_TAMPALRM_TYPE) && defined(RTC_CR_OUT2EN)
+ hrtc->Instance->CR &= ~(RTC_CR_TAMPALRM_PU | RTC_CR_TAMPALRM_TYPE | RTC_CR_OUT2EN);
+ hrtc->Instance->CR |= (hrtc->Init.OutPutPullUp | hrtc->Init.OutPutType | hrtc->Init.OutPutRemap);
+#endif /* RTC_CR_TAMPALRM_TYPE && RTC_CR_OUT2EN && RTC_CR_TAMPALRM_PU */
+
+#if defined(RTC_OR_ALARMOUTTYPE) && defined(RTC_OR_OUT_RMP)
+ hrtc->Instance->OR &= ~(RTC_OR_ALARMOUTTYPE | RTC_OR_OUT_RMP);
+ hrtc->Instance->OR |= (hrtc->Init.OutPutType | hrtc->Init.OutPutRemap);
+#endif /* ALARMOUTTYPE && RTC_OR_OUT_RMP */
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+ }
+ }
+ }
+
+ /* return status */
+ return status;
+}
+
+/**
+ * @brief DeInitialize the RTC peripheral.
+ * @note This function doesn't reset the RTC Backup Data registers.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+ uint32_t tickstart;
+
+ /* Check RTC handler */
+ if(hrtc != NULL)
+ {
+ status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Reset TR, DR and CR registers */
+ hrtc->Instance->TR = 0x00000000U;
+ hrtc->Instance->DR = ((uint32_t)(RTC_DR_WDU_0 | RTC_DR_MU_0 | RTC_DR_DU_0));
+ /* Reset All CR bits except CR[2:0] */
+ hrtc->Instance->CR &= RTC_CR_WUCKSEL;
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till WUTWF flag is set and if Time out is reached exit */
+#if defined(RTC_ICSR_WUTWF)
+ while (((hrtc->Instance->ICSR) & RTC_ICSR_WUTWF) == 0U)
+#endif /* RTC_ICSR_WUTWF */
+#if defined(RTC_ISR_WUTWF)
+ while (((hrtc->Instance->ISR) & RTC_ISR_WUTWF) == 0U)
+#endif /* RTC_ISR_WUTWF */
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ status = HAL_TIMEOUT;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Reset all RTC CR register bits */
+ hrtc->Instance->CR &= 0x00000000U;
+
+ /* Reset other RTC registers */
+ hrtc->Instance->WUTR = RTC_WUTR_WUT;
+ hrtc->Instance->PRER = ((uint32_t)(RTC_PRER_PREDIV_A | 0x000000FFU));
+ hrtc->Instance->ALRMAR = 0x00000000U;
+ hrtc->Instance->ALRMBR = 0x00000000U;
+ hrtc->Instance->SHIFTR = 0x00000000U;
+ hrtc->Instance->CALR = 0x00000000U;
+ hrtc->Instance->ALRMASSR = 0x00000000U;
+ hrtc->Instance->ALRMBSSR = 0x00000000U;
+
+#if defined(RTC_ICSR_INIT)
+ /* Exit initialization mode */
+ CLEAR_BIT(hrtc->Instance->ICSR, RTC_ICSR_INIT);
+#endif /* RTC_ICSR_INIT */
+#if defined(RTC_ISR_INIT)
+ /* Reset ISR register and exit initialization mode */
+ hrtc->Instance->ISR = 0x00000000U;
+
+ /* Reset Tamper configuration register */
+ hrtc->Instance->TAMPCR = 0x00000000U;
+
+ /* Reset Option register */
+ hrtc->Instance->OR = 0x00000000U;
+#endif /* RTC_ISR_INIT */
+
+ /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == 0U)
+ {
+ if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ status = HAL_ERROR;
+ }
+ }
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+#if defined(TAMP_CR1_TAMP1E)
+ /* Reset TAMP registers */
+ ((TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET))->CR1 = 0xFFFF0000U;
+ ((TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET))->CR2 = 0x00000000U;
+#endif /* TAMP_CR1_TAMP1E */
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ if(hrtc->MspDeInitCallback == NULL)
+ {
+ hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
+ }
+
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ hrtc->MspDeInitCallback(hrtc);
+#else
+ /* De-Initialize RTC MSP */
+ HAL_RTC_MspDeInit(hrtc);
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS) */
+
+ hrtc->State = HAL_RTC_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrtc);
+ }
+ }
+
+ /* return status */
+ return status;
+}
+
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User RTC Callback
+ * To be used instead of the weak predefined callback
+ * @param hrtc RTC handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID
+ * @arg @ref HAL_RTC_ALARM_B_EVENT_CB_ID Alarm B Event Callback ID
+ * @arg @ref HAL_RTC_TIMESTAMP_EVENT_CB_ID TimeStamp Event Callback ID
+ * @arg @ref HAL_RTC_WAKEUPTIMER_EVENT_CB_ID WakeUp Timer Event Callback ID
+ * @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Callback ID
+ * @arg @ref HAL_RTC_TAMPER2_EVENT_CB_ID Tamper 2 Callback ID
+ * @arg @ref HAL_RTC_TAMPER3_EVENT_CB_ID Tamper 3 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER1_EVENT_CB_ID Internal Tamper 1 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER2_EVENT_CB_ID Internal Tamper 2 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER3_EVENT_CB_ID Internal Tamper 3 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER4_EVENT_CB_ID Internal Tamper 4 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER5_EVENT_CB_ID Internal Tamper 5 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER6_EVENT_CB_ID Internal Tamper 6 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER8_EVENT_CB_ID Internal Tamper 8 Callback ID
+ * @arg @ref HAL_RTC_MSPINIT_CB_ID Msp Init callback ID
+ * @arg @ref HAL_RTC_MSPDEINIT_CB_ID Msp DeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_RegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID, pRTC_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hrtc);
+
+ if(HAL_RTC_STATE_READY == hrtc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RTC_ALARM_A_EVENT_CB_ID :
+ hrtc->AlarmAEventCallback = pCallback;
+ break;
+
+ case HAL_RTC_ALARM_B_EVENT_CB_ID :
+ hrtc->AlarmBEventCallback = pCallback;
+ break;
+
+ case HAL_RTC_TIMESTAMP_EVENT_CB_ID :
+ hrtc->TimeStampEventCallback = pCallback;
+ break;
+
+ case HAL_RTC_WAKEUPTIMER_EVENT_CB_ID :
+ hrtc->WakeUpTimerEventCallback = pCallback;
+ break;
+
+ case HAL_RTC_TAMPER1_EVENT_CB_ID :
+ hrtc->Tamper1EventCallback = pCallback;
+ break;
+
+ case HAL_RTC_TAMPER2_EVENT_CB_ID :
+ hrtc->Tamper2EventCallback = pCallback;
+ break;
+
+ case HAL_RTC_TAMPER3_EVENT_CB_ID :
+ hrtc->Tamper3EventCallback = pCallback;
+ break;
+
+#if defined(TAMP_CR1_ITAMP1E)
+ case HAL_RTC_INTERNAL_TAMPER1_EVENT_CB_ID :
+ hrtc->InternalTamper1EventCallback = pCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP1E */
+
+#if defined(TAMP_CR1_ITAMP2E)
+ case HAL_RTC_INTERNAL_TAMPER2_EVENT_CB_ID :
+ hrtc->InternalTamper2EventCallback = pCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP2E */
+
+#if defined(TAMP_CR1_ITAMP3E)
+ case HAL_RTC_INTERNAL_TAMPER3_EVENT_CB_ID :
+ hrtc->InternalTamper3EventCallback = pCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP3E */
+
+#if defined(TAMP_CR1_ITAMP4E)
+ case HAL_RTC_INTERNAL_TAMPER4_EVENT_CB_ID :
+ hrtc->InternalTamper4EventCallback = pCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP4E */
+
+#if defined(TAMP_CR1_ITAMP5E)
+ case HAL_RTC_INTERNAL_TAMPER5_EVENT_CB_ID :
+ hrtc->InternalTamper5EventCallback = pCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP5E */
+
+#if defined(TAMP_CR1_ITAMP6E)
+ case HAL_RTC_INTERNAL_TAMPER6_EVENT_CB_ID :
+ hrtc->InternalTamper6EventCallback = pCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP6E */
+
+#if defined(TAMP_CR1_ITAMP8E)
+ case HAL_RTC_INTERNAL_TAMPER8_EVENT_CB_ID :
+ hrtc->InternalTamper8EventCallback = pCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP8E */
+
+ case HAL_RTC_MSPINIT_CB_ID :
+ hrtc->MspInitCallback = pCallback;
+ break;
+
+ case HAL_RTC_MSPDEINIT_CB_ID :
+ hrtc->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_RTC_STATE_RESET == hrtc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RTC_MSPINIT_CB_ID :
+ hrtc->MspInitCallback = pCallback;
+ break;
+
+ case HAL_RTC_MSPDEINIT_CB_ID :
+ hrtc->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrtc);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an RTC Callback
+ * RTC callabck is redirected to the weak predefined callback
+ * @param hrtc RTC handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID
+ * @arg @ref HAL_RTC_ALARM_B_EVENT_CB_ID Alarm B Event Callback ID
+ * @arg @ref HAL_RTC_TIMESTAMP_EVENT_CB_ID TimeStamp Event Callback ID
+ * @arg @ref HAL_RTC_WAKEUPTIMER_EVENT_CB_ID WakeUp Timer Event Callback ID
+ * @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Callback ID
+ * @arg @ref HAL_RTC_TAMPER2_EVENT_CB_ID Tamper 2 Callback ID
+ * @arg @ref HAL_RTC_TAMPER3_EVENT_CB_ID Tamper 3 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER1_EVENT_CB_ID Internal Tamper 1 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER2_EVENT_CB_ID Internal Tamper 2 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER3_EVENT_CB_ID Internal Tamper 3 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER4_EVENT_CB_ID Internal Tamper 4 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER5_EVENT_CB_ID Internal Tamper 5 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER6_EVENT_CB_ID Internal Tamper 6 Callback ID
+ * @arg @ref HAL_RTC_INTERNAL_TAMPER8_EVENT_CB_ID Internal Tamper 8 Callback ID
+ * @arg @ref HAL_RTC_MSPINIT_CB_ID Msp Init callback ID
+ * @arg @ref HAL_RTC_MSPDEINIT_CB_ID Msp DeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_UnRegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hrtc);
+
+ if(HAL_RTC_STATE_READY == hrtc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RTC_ALARM_A_EVENT_CB_ID :
+ hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */
+ break;
+
+ case HAL_RTC_ALARM_B_EVENT_CB_ID :
+ hrtc->AlarmBEventCallback = HAL_RTCEx_AlarmBEventCallback; /* Legacy weak AlarmBEventCallback */
+ break;
+
+ case HAL_RTC_TIMESTAMP_EVENT_CB_ID :
+ hrtc->TimeStampEventCallback = HAL_RTCEx_TimeStampEventCallback; /* Legacy weak TimeStampEventCallback */
+ break;
+
+ case HAL_RTC_WAKEUPTIMER_EVENT_CB_ID :
+ hrtc->WakeUpTimerEventCallback = HAL_RTCEx_WakeUpTimerEventCallback; /* Legacy weak WakeUpTimerEventCallback */
+ break;
+
+ case HAL_RTC_TAMPER1_EVENT_CB_ID :
+ hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */
+ break;
+
+ case HAL_RTC_TAMPER2_EVENT_CB_ID :
+ hrtc->Tamper2EventCallback = HAL_RTCEx_Tamper2EventCallback; /* Legacy weak Tamper2EventCallback */
+ break;
+
+ case HAL_RTC_TAMPER3_EVENT_CB_ID :
+ hrtc->Tamper3EventCallback = HAL_RTCEx_Tamper3EventCallback; /* Legacy weak Tamper3EventCallback */
+ break;
+
+#if defined(TAMP_CR1_ITAMP1E)
+ case HAL_RTC_INTERNAL_TAMPER1_EVENT_CB_ID :
+ hrtc->InternalTamper1EventCallback = HAL_RTCEx_InternalTamper1EventCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP1E */
+
+#if defined(TAMP_CR1_ITAMP2E)
+ case HAL_RTC_INTERNAL_TAMPER2_EVENT_CB_ID :
+ hrtc->InternalTamper2EventCallback = HAL_RTCEx_InternalTamper2EventCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP2E */
+
+#if defined(TAMP_CR1_ITAMP3E)
+ case HAL_RTC_INTERNAL_TAMPER3_EVENT_CB_ID :
+ hrtc->InternalTamper3EventCallback = HAL_RTCEx_InternalTamper3EventCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP3E */
+
+#if defined(TAMP_CR1_ITAMP4E)
+ case HAL_RTC_INTERNAL_TAMPER4_EVENT_CB_ID :
+ hrtc->InternalTamper4EventCallback = HAL_RTCEx_InternalTamper4EventCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP4E */
+
+#if defined(TAMP_CR1_ITAMP5E)
+ case HAL_RTC_INTERNAL_TAMPER5_EVENT_CB_ID :
+ hrtc->InternalTamper5EventCallback = HAL_RTCEx_InternalTamper5EventCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP5E */
+
+#if defined(TAMP_CR1_ITAMP6E)
+ case HAL_RTC_INTERNAL_TAMPER6_EVENT_CB_ID :
+ hrtc->InternalTamper6EventCallback = HAL_RTCEx_InternalTamper6EventCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP6E */
+
+#if defined(TAMP_CR1_ITAMP8E)
+ case HAL_RTC_INTERNAL_TAMPER8_EVENT_CB_ID :
+ hrtc->InternalTamper8EventCallback = HAL_RTCEx_InternalTamper8EventCallback;
+ break;
+#endif /* TAMP_CR1_ITAMP8E */
+
+ case HAL_RTC_MSPINIT_CB_ID :
+ hrtc->MspInitCallback = HAL_RTC_MspInit;
+ break;
+
+ case HAL_RTC_MSPDEINIT_CB_ID :
+ hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_RTC_STATE_RESET == hrtc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RTC_MSPINIT_CB_ID :
+ hrtc->MspInitCallback = HAL_RTC_MspInit;
+ break;
+
+ case HAL_RTC_MSPDEINIT_CB_ID :
+ hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrtc);
+
+ return status;
+}
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+
+/**
+ * @brief Initialize the RTC MSP.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the RTC MSP.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTC_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTC_Exported_Functions_Group2
+ * @brief RTC Time and Date functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Time and Date functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Time and Date features
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set RTC current time.
+ * @param hrtc RTC handle
+ * @param sTime Pointer to Time structure
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_DAYLIGHT_SAVING(sTime->DayLightSaving));
+ assert_param(IS_RTC_STORE_OPERATION(sTime->StoreOperation));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ if(Format == RTC_FORMAT_BIN)
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(sTime->Hours));
+ assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat));
+ }
+ else
+ {
+ sTime->TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(sTime->Hours));
+ }
+ assert_param(IS_RTC_MINUTES(sTime->Minutes));
+ assert_param(IS_RTC_SECONDS(sTime->Seconds));
+
+ tmpreg = (uint32_t)(((uint32_t)RTC_ByteToBcd2(sTime->Hours) << RTC_TR_HU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sTime->Minutes) << RTC_TR_MNU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sTime->Seconds) << RTC_TR_SU_Pos) | \
+ (((uint32_t)sTime->TimeFormat) << RTC_TR_PM_Pos));
+ }
+ else
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(RTC_Bcd2ToByte(sTime->Hours)));
+ assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat));
+ }
+ else
+ {
+ sTime->TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours)));
+ }
+ assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes)));
+ assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds)));
+ tmpreg = (((uint32_t)(sTime->Hours) << RTC_TR_HU_Pos) | \
+ ((uint32_t)(sTime->Minutes) << RTC_TR_MNU_Pos) | \
+ ((uint32_t)(sTime->Seconds) << RTC_TR_SU_Pos) | \
+ ((uint32_t)(sTime->TimeFormat) << RTC_TR_PM_Pos));
+ }
+
+ /* Set the RTC_TR register */
+ hrtc->Instance->TR = (uint32_t)(tmpreg & RTC_TR_RESERVED_MASK);
+
+ /* Clear the bits to be configured */
+ hrtc->Instance->CR &= ((uint32_t)~RTC_CR_BKP);
+
+ /* Configure the RTC_CR register */
+ hrtc->Instance->CR |= (uint32_t)(sTime->DayLightSaving | sTime->StoreOperation);
+
+ /* Exit Initialization mode */
+#if defined(RTC_ICSR_INIT)
+ CLEAR_BIT(hrtc->Instance->ICSR, RTC_ICSR_INIT);
+#endif /* RTC_ICSR_INIT */
+#if defined(RTC_ISR_INIT)
+ CLEAR_BIT(hrtc->Instance->ISR, RTC_ISR_INIT);
+#endif /* RTC_ISR_INIT */
+
+ /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == 0U)
+ {
+ if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Get RTC current time.
+ * @param hrtc RTC handle
+ * @param sTime Pointer to Time structure with Hours, Minutes and Seconds fields returned
+ * with input format (BIN or BCD), also SubSeconds field returning the
+ * RTC_SSR register content and SecondFraction field the Synchronous pre-scaler
+ * factor to be used for second fraction ratio computation.
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note You can use SubSeconds and SecondFraction (sTime structure fields returned) to convert SubSeconds
+ * value in second fraction ratio with time unit following generic formula:
+ * Second fraction ratio * time_unit= [(SecondFraction-SubSeconds)/(SecondFraction+1)] * time_unit
+ * This conversion can be performed only if no shift operation is pending (ie. SHFP=0) when PREDIV_S >= SS
+ * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values
+ * in the higher-order calendar shadow registers to ensure consistency between the time and date values.
+ * Reading RTC current time locks the values in calendar shadow registers until Current date is read
+ * to ensure consistency between the time and date values.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Get subseconds structure field from the corresponding register*/
+ sTime->SubSeconds = (uint32_t)(hrtc->Instance->SSR);
+
+ /* Get SecondFraction structure field from the corresponding register field*/
+ sTime->SecondFraction = (uint32_t)(hrtc->Instance->PRER & RTC_PRER_PREDIV_S);
+
+ /* Get the TR register */
+ tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK);
+
+ /* Fill the structure fields with the read parameters */
+ sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> RTC_TR_HU_Pos);
+ sTime->Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >> RTC_TR_MNU_Pos);
+ sTime->Seconds = (uint8_t)((tmpreg & (RTC_TR_ST | RTC_TR_SU)) >> RTC_TR_SU_Pos);
+ sTime->TimeFormat = (uint8_t)((tmpreg & (RTC_TR_PM)) >> RTC_TR_PM_Pos);
+
+ /* Check the input parameters format */
+ if(Format == RTC_FORMAT_BIN)
+ {
+ /* Convert the time structure parameters to Binary format */
+ sTime->Hours = (uint8_t)RTC_Bcd2ToByte(sTime->Hours);
+ sTime->Minutes = (uint8_t)RTC_Bcd2ToByte(sTime->Minutes);
+ sTime->Seconds = (uint8_t)RTC_Bcd2ToByte(sTime->Seconds);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set RTC current date.
+ * @param hrtc RTC handle
+ * @param sDate Pointer to date structure
+ * @param Format specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
+{
+ uint32_t datetmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ if((Format == RTC_FORMAT_BIN) && ((sDate->Month & 0x10U) == 0x10U))
+ {
+ sDate->Month = (uint8_t)((sDate->Month & (uint8_t)~(0x10U)) + (uint8_t)0x0AU);
+ }
+
+ assert_param(IS_RTC_WEEKDAY(sDate->WeekDay));
+
+ if(Format == RTC_FORMAT_BIN)
+ {
+ assert_param(IS_RTC_YEAR(sDate->Year));
+ assert_param(IS_RTC_MONTH(sDate->Month));
+ assert_param(IS_RTC_DATE(sDate->Date));
+
+ datetmpreg = (((uint32_t)RTC_ByteToBcd2(sDate->Year) << RTC_DR_YU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sDate->Month) << RTC_DR_MU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sDate->Date) << RTC_DR_DU_Pos) | \
+ ((uint32_t)sDate->WeekDay << RTC_DR_WDU_Pos));
+ }
+ else
+ {
+ assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(sDate->Year)));
+ assert_param(IS_RTC_MONTH(RTC_Bcd2ToByte(sDate->Month)));
+ assert_param(IS_RTC_DATE(RTC_Bcd2ToByte(sDate->Date)));
+
+ datetmpreg = ((((uint32_t)sDate->Year) << RTC_DR_YU_Pos) | \
+ (((uint32_t)sDate->Month) << RTC_DR_MU_Pos) | \
+ (((uint32_t)sDate->Date) << RTC_DR_DU_Pos) | \
+ (((uint32_t)sDate->WeekDay) << RTC_DR_WDU_Pos));
+ }
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state*/
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Set the RTC_DR register */
+ hrtc->Instance->DR = (uint32_t)(datetmpreg & RTC_DR_RESERVED_MASK);
+
+ /* Exit Initialization mode */
+#if defined(RTC_ICSR_INIT)
+ CLEAR_BIT(hrtc->Instance->ICSR, RTC_ICSR_INIT);
+#endif /* RTC_ISR_INIT */
+#if defined(RTC_ISR_INIT)
+ CLEAR_BIT(hrtc->Instance->ISR, RTC_ISR_INIT);
+#endif /* RTC_ISR_INIT */
+
+ /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == 0U)
+ {
+ if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY ;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Get RTC current date.
+ * @param hrtc RTC handle
+ * @param sDate Pointer to Date structure
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values
+ * in the higher-order calendar shadow registers to ensure consistency between the time and date values.
+ * Reading RTC current time locks the values in calendar shadow registers until Current date is read.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
+{
+ uint32_t datetmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Get the DR register */
+ datetmpreg = (uint32_t)(hrtc->Instance->DR & RTC_DR_RESERVED_MASK);
+
+ /* Fill the structure fields with the read parameters */
+ sDate->Year = (uint8_t)((datetmpreg & (RTC_DR_YT | RTC_DR_YU)) >> RTC_DR_YU_Pos);
+ sDate->Month = (uint8_t)((datetmpreg & (RTC_DR_MT | RTC_DR_MU)) >> RTC_DR_MU_Pos);
+ sDate->Date = (uint8_t)((datetmpreg & (RTC_DR_DT | RTC_DR_DU)) >> RTC_DR_DU_Pos);
+ sDate->WeekDay = (uint8_t)((datetmpreg & (RTC_DR_WDU)) >> RTC_DR_WDU_Pos);
+
+ /* Check the input parameters format */
+ if(Format == RTC_FORMAT_BIN)
+ {
+ /* Convert the date structure parameters to Binary format */
+ sDate->Year = (uint8_t)RTC_Bcd2ToByte(sDate->Year);
+ sDate->Month = (uint8_t)RTC_Bcd2ToByte(sDate->Month);
+ sDate->Date = (uint8_t)RTC_Bcd2ToByte(sDate->Date);
+ }
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTC_Exported_Functions_Group3
+ * @brief RTC Alarm functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Alarm functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Alarm feature
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Set the specified RTC Alarm.
+ * @param hrtc RTC handle
+ * @param sAlarm Pointer to Alarm structure
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
+{
+ uint32_t tickstart;
+ uint32_t tmpreg;
+ uint32_t subsecondtmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_ALARM(sAlarm->Alarm));
+ assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask));
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ if(Format == RTC_FORMAT_BIN)
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
+ }
+ assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
+ assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
+
+ if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay));
+ }
+
+ tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds) << RTC_ALRMAR_SU_Pos) | \
+ ((uint32_t)sAlarm->AlarmTime.TimeFormat << RTC_ALRMAR_PM_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+ else
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ }
+
+ assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
+ assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
+
+ if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay)));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay)));
+ }
+
+ tmpreg = (((uint32_t)sAlarm->AlarmTime.Hours << RTC_ALRMAR_HU_Pos) | \
+ ((uint32_t)sAlarm->AlarmTime.Minutes << RTC_ALRMAR_MNU_Pos) | \
+ ((uint32_t)sAlarm->AlarmTime.Seconds << RTC_ALRMAR_SU_Pos) | \
+ ((uint32_t)sAlarm->AlarmTime.TimeFormat << RTC_ALRMAR_PM_Pos) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDay << RTC_ALRMAR_DU_Pos) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+
+ /* Configure the Alarm A or Alarm B Sub Second registers */
+ subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | (uint32_t)(sAlarm->AlarmSubSecondMask));
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the Alarm register */
+ if(sAlarm->Alarm == RTC_ALARM_A)
+ {
+ /* Disable the Alarm A interrupt */
+ __HAL_RTC_ALARMA_DISABLE(hrtc);
+ /* Clear flag alarm A */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */
+ #if defined(RTC_ICSR_ALRAWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_ALRAWF) == 0U)
+ #endif /* RTC_ICSR_ALRAWF */
+ #if defined(RTC_ISR_ALRAWF)
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == 0U)
+ #endif /* RTC_ISR_ALRAWF */
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ hrtc->Instance->ALRMAR = (uint32_t)tmpreg;
+ /* Configure the Alarm A Sub Second register */
+ hrtc->Instance->ALRMASSR = subsecondtmpreg;
+ /* Configure the Alarm state: Enable Alarm */
+ __HAL_RTC_ALARMA_ENABLE(hrtc);
+ }
+ else
+ {
+ /* Disable the Alarm B interrupt */
+ __HAL_RTC_ALARMB_DISABLE(hrtc);
+ /* Clear flag alarm B */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRB);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC ALRBWF flag is set and if Time out is reached exit */
+ #if defined(RTC_ICSR_ALRBWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_ALRBWF) == 0U)
+ #endif /* RTC_ICSR_ALRBWF */
+ #if defined(RTC_ISR_ALRBWF)
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == 0U)
+ #endif /* RTC_ISR_ALRBWF */
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ hrtc->Instance->ALRMBR = (uint32_t)tmpreg;
+ /* Configure the Alarm B Sub Second register */
+ hrtc->Instance->ALRMBSSR = subsecondtmpreg;
+ /* Configure the Alarm state: Enable Alarm */
+ __HAL_RTC_ALARMB_ENABLE(hrtc);
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the specified RTC Alarm with Interrupt.
+ * @param hrtc RTC handle
+ * @param sAlarm Pointer to Alarm structure
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note The Alarm register can only be written when the corresponding Alarm
+ * is disabled (Use the HAL_RTC_DeactivateAlarm()).
+ * @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
+{
+ uint32_t tickstart;
+ uint32_t tmpreg;
+ uint32_t subsecondtmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_ALARM(sAlarm->Alarm));
+ assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask));
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ if(Format == RTC_FORMAT_BIN)
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
+ }
+ assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
+ assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
+
+ if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay));
+ }
+
+ tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds) << RTC_ALRMAR_SU_Pos) | \
+ ((uint32_t)sAlarm->AlarmTime.TimeFormat << RTC_ALRMAR_PM_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+ else
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ }
+
+ assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
+ assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
+
+ if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay)));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay)));
+ }
+
+ tmpreg = (((uint32_t)sAlarm->AlarmTime.Hours << RTC_ALRMAR_HU_Pos) | \
+ ((uint32_t)sAlarm->AlarmTime.Minutes << RTC_ALRMAR_MNU_Pos) | \
+ ((uint32_t)sAlarm->AlarmTime.Seconds << RTC_ALRMAR_SU_Pos) | \
+ ((uint32_t)sAlarm->AlarmTime.TimeFormat << RTC_ALRMAR_PM_Pos) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDay << RTC_ALRMAR_DU_Pos) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+ /* Configure the Alarm A or Alarm B Sub Second registers */
+ subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | (uint32_t)(sAlarm->AlarmSubSecondMask));
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the Alarm register */
+ if(sAlarm->Alarm == RTC_ALARM_A)
+ {
+ /* Disable the Alarm A interrupt */
+ __HAL_RTC_ALARMA_DISABLE(hrtc);
+
+ /* Clear flag alarm A */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */
+ #if defined(RTC_ICSR_ALRAWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_ALRAWF) == 0U)
+ #endif /* RTC_ICSR_ALRAWF */
+ #if defined(RTC_ISR_ALRAWF)
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == 0U)
+ #endif /* RTC_ISR_ALRAWF */
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ hrtc->Instance->ALRMAR = (uint32_t)tmpreg;
+ /* Configure the Alarm A Sub Second register */
+ hrtc->Instance->ALRMASSR = subsecondtmpreg;
+ /* Configure the Alarm state: Enable Alarm */
+ __HAL_RTC_ALARMA_ENABLE(hrtc);
+ /* Configure the Alarm interrupt */
+ __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRA);
+ }
+ else
+ {
+ /* Disable the Alarm B interrupt */
+ __HAL_RTC_ALARMB_DISABLE(hrtc);
+
+ /* Clear flag alarm B */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC ALRBWF flag is set and if Time out is reached exit */
+#if defined(RTC_ICSR_ALRBWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_ALRBWF) == 0U)
+#endif /* RTC_ICSR_ALRBWF */
+#if defined(RTC_ISR_ALRBWF)
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == 0U)
+#endif /* RTC_ISR_ALRBWF */
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ hrtc->Instance->ALRMBR = (uint32_t)tmpreg;
+ /* Configure the Alarm B Sub Second register */
+ hrtc->Instance->ALRMBSSR = subsecondtmpreg;
+ /* Configure the Alarm state: Enable Alarm */
+ __HAL_RTC_ALARMB_ENABLE(hrtc);
+ /* Configure the Alarm interrupt */
+ __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRB);
+ }
+
+#if !defined(DUAL_CORE)
+ /* RTC Alarm Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_ALARM_EXTI_ENABLE_IT();
+#endif
+
+ __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate the specified RTC Alarm.
+ * @param hrtc RTC handle
+ * @param Alarm Specifies the Alarm.
+ * This parameter can be one of the following values:
+ * @arg RTC_ALARM_A: AlarmA
+ * @arg RTC_ALARM_B: AlarmB
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALARM(Alarm));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ if(Alarm == RTC_ALARM_A)
+ {
+ /* AlarmA */
+ __HAL_RTC_ALARMA_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRxWF flag is set and if Time out is reached exit */
+#if defined(RTC_ICSR_ALRAWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_ALRAWF) == 0U)
+#endif /* RTC_ICSR_ALRAWF */
+#if defined(RTC_ISR_ALRAWF)
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == 0U)
+#endif /* RTC_ISR_ALRAWF */
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* AlarmB */
+ __HAL_RTC_ALARMB_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRB);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRxWF flag is set and if Time out is reached exit */
+#if defined(RTC_ICSR_ALRBWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_ALRBWF) == 0U)
+#endif /* RTC_ICSR_ALRBWF */
+#if defined(RTC_ISR_ALRBWF)
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == 0U)
+#endif /* RTC_ISR_ALRBWF */
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the RTC Alarm value and masks.
+ * @param hrtc RTC handle
+ * @param sAlarm Pointer to Date structure
+ * @param Alarm Specifies the Alarm.
+ * This parameter can be one of the following values:
+ * @arg RTC_ALARM_A: AlarmA
+ * @arg RTC_ALARM_B: AlarmB
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format)
+{
+ uint32_t tmpreg;
+ uint32_t subsecondtmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_ALARM(Alarm));
+
+ if(Alarm == RTC_ALARM_A)
+ {
+ /* AlarmA */
+ sAlarm->Alarm = RTC_ALARM_A;
+
+ tmpreg = (uint32_t)(hrtc->Instance->ALRMAR);
+ subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMASSR) & RTC_ALRMASSR_SS);
+
+ /* Fill the structure with the read parameters */
+ sAlarm->AlarmTime.Hours = (uint8_t)((tmpreg & (RTC_ALRMAR_HT | RTC_ALRMAR_HU)) >> RTC_ALRMAR_HU_Pos);
+ sAlarm->AlarmTime.Minutes = (uint8_t)((tmpreg & (RTC_ALRMAR_MNT | RTC_ALRMAR_MNU)) >> RTC_ALRMAR_MNU_Pos);
+ sAlarm->AlarmTime.Seconds = (uint8_t)((tmpreg & (RTC_ALRMAR_ST | RTC_ALRMAR_SU)) >> RTC_ALRMAR_SU_Pos);
+ sAlarm->AlarmTime.TimeFormat = (uint8_t)((tmpreg & RTC_ALRMAR_PM) >> RTC_ALRMAR_PM_Pos);
+ sAlarm->AlarmTime.SubSeconds = (uint32_t) subsecondtmpreg;
+ sAlarm->AlarmDateWeekDay = (uint8_t)((tmpreg & (RTC_ALRMAR_DT | RTC_ALRMAR_DU)) >> RTC_ALRMAR_DU_Pos);
+ sAlarm->AlarmDateWeekDaySel = (uint32_t)(tmpreg & RTC_ALRMAR_WDSEL);
+ sAlarm->AlarmMask = (uint32_t)(tmpreg & RTC_ALARMMASK_ALL);
+ }
+ else
+ {
+ sAlarm->Alarm = RTC_ALARM_B;
+
+ tmpreg = (uint32_t)(hrtc->Instance->ALRMBR);
+ subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMBSSR) & RTC_ALRMBSSR_SS);
+
+ /* Fill the structure with the read parameters */
+ sAlarm->AlarmTime.Hours = (uint8_t)((tmpreg & (RTC_ALRMBR_HT | RTC_ALRMBR_HU)) >> RTC_ALRMBR_HU_Pos);
+ sAlarm->AlarmTime.Minutes = (uint8_t)((tmpreg & (RTC_ALRMBR_MNT | RTC_ALRMBR_MNU)) >> RTC_ALRMBR_MNU_Pos);
+ sAlarm->AlarmTime.Seconds = (uint8_t)((tmpreg & (RTC_ALRMBR_ST | RTC_ALRMBR_SU)) >> RTC_ALRMBR_SU_Pos);
+ sAlarm->AlarmTime.TimeFormat = (uint8_t)((tmpreg & RTC_ALRMBR_PM) >> RTC_ALRMBR_PM_Pos);
+ sAlarm->AlarmTime.SubSeconds = (uint32_t) subsecondtmpreg;
+ sAlarm->AlarmDateWeekDay = (uint8_t)((tmpreg & (RTC_ALRMBR_DT | RTC_ALRMBR_DU)) >> RTC_ALRMBR_DU_Pos);
+ sAlarm->AlarmDateWeekDaySel = (uint32_t)(tmpreg & RTC_ALRMBR_WDSEL);
+ sAlarm->AlarmMask = (uint32_t)(tmpreg & RTC_ALARMMASK_ALL);
+ }
+
+ if(Format == RTC_FORMAT_BIN)
+ {
+ sAlarm->AlarmTime.Hours = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours);
+ sAlarm->AlarmTime.Minutes = RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes);
+ sAlarm->AlarmTime.Seconds = RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds);
+ sAlarm->AlarmDateWeekDay = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle Alarm interrupt request.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ /* Clear the EXTI's line Flag for RTC Alarm */
+#if defined(DUAL_CORE)
+ if(HAL_GetCurrentCPUID() == CM7_CPUID)
+ {
+ __HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
+ }
+ else
+ {
+ __HAL_RTC_ALARM_EXTID2_CLEAR_FLAG();
+ }
+#else /* SINGLE_CORE */
+ __HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
+#endif /* DUAL_CORE */
+
+#if defined(RTC_MISR_ALRAMF)
+ /* Get interrupt status */
+ uint32_t tmp = hrtc->Instance->MISR;
+
+ if((tmp & RTC_MISR_ALRAMF) != 0u)
+ {
+ /* Clear the AlarmA interrupt pending bit */
+ hrtc->Instance->SCR = RTC_SCR_CALRAF;
+
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Compare Match registered Callback */
+ hrtc->AlarmAEventCallback(hrtc);
+#else /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ HAL_RTC_AlarmAEventCallback(hrtc);
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ }
+#endif /* RTC_MISR_ALRAMF */
+
+#if defined(RTC_MISR_ALRBMF)
+ if((tmp & RTC_MISR_ALRBMF) != 0u)
+ {
+ /* Clear the AlarmB interrupt pending bit */
+ hrtc->Instance->SCR = RTC_SCR_CALRBF;
+
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Compare Match registered Callback */
+ hrtc->AlarmBEventCallback(hrtc);
+#else /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ HAL_RTCEx_AlarmBEventCallback(hrtc);
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ }
+#endif /* RTC_MISR_ALRBMF */
+
+#if defined(RTC_ISR_ALRAF)
+ /* Get the AlarmA interrupt source enable status */
+ if(__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != 0U)
+ {
+ /* Get the pending status of the AlarmA Interrupt */
+ if(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != 0U)
+ {
+ /* Clear the AlarmA interrupt pending bit */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->AlarmAEventCallback(hrtc);
+#else /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ HAL_RTC_AlarmAEventCallback(hrtc);
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ }
+ }
+#endif /* RTC_ISR_ALRAF */
+
+#if defined(RTC_ISR_ALRBF)
+ /* Get the AlarmB interrupt source enable status */
+ if(__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRB) != 0U)
+ {
+ /* Get the pending status of the AlarmB Interrupt */
+ if(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) != 0U)
+ {
+ /* Clear the AlarmB interrupt pending bit */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+
+ /* AlarmB callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->AlarmBEventCallback(hrtc);
+#else /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ HAL_RTCEx_AlarmBEventCallback(hrtc);
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ }
+ }
+#endif /* RTC_ISR_ALRBF */
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+
+/**
+ * @brief Alarm A callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTC_AlarmAEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Handle AlarmA Polling request.
+ * @param hrtc RTC handle
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+
+ uint32_t tickstart = HAL_GetTick();
+
+ while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) == 0U)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Alarm interrupt pending bit */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTC_Exported_Functions_Group4
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Wait for RTC Time and Date Synchronization
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Wait until the RTC Time and Date registers (RTC_TR and RTC_DR) are
+ * synchronized with RTC APB clock.
+ * @note The RTC Resynchronization mode is write protected, use the
+ * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function.
+ * @note To read the calendar through the shadow registers after Calendar
+ * initialization, calendar update or after wakeup from low power modes
+ * the software must first clear the RSF flag.
+ * The software must then wait until it is set again before reading
+ * the calendar, which means that the calendar registers have been
+ * correctly copied into the RTC_TR and RTC_DR shadow registers.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tickstart;
+
+ /* Clear RSF flag */
+#if defined(RTC_ICSR_RSF)
+ hrtc->Instance->ICSR &= (uint32_t)RTC_RSF_MASK;
+#endif /* RTC_ICSR_RSF */
+#if defined(RTC_ISR_RSF)
+ hrtc->Instance->ISR &= (uint32_t)RTC_RSF_MASK;
+#endif /* RTC_ISR_RSF */
+
+ tickstart = HAL_GetTick();
+
+ /* Wait the registers to be synchronised */
+#if defined(RTC_ICSR_RSF)
+ while ((hrtc->Instance->ICSR & RTC_ICSR_RSF) == 0U)
+#endif /* RTC_ICSR_RSF */
+#if defined(RTC_ISR_RSF)
+ while ((hrtc->Instance->ISR & RTC_ISR_RSF) == 0U)
+#endif /* RTC_ISR_RSF */
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTC_Exported_Functions_Group5
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Get RTC state
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Return the RTC handle state.
+ * @param hrtc RTC handle
+ * @retval HAL state
+ */
+HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc)
+{
+ /* Return RTC handle state */
+ return hrtc->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTC_Private_Functions
+ * @{
+ */
+/**
+ * @brief Enter the RTC Initialization mode.
+ * @note The RTC Initialization mode is write protected, use the
+ * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tickstart;
+
+ /* Check if the Initialization mode is set */
+#if defined(RTC_ICSR_INITF)
+ if((hrtc->Instance->ICSR & RTC_ICSR_INITF) == 0U)
+ {
+ /* Set the Initialization mode */
+ SET_BIT(hrtc->Instance->ICSR, RTC_ICSR_INIT);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC is in INIT state and if Time out is reached exit */
+ while ((hrtc->Instance->ICSR & RTC_ICSR_INITF) == 0U)
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+#endif /* RTC_ICSR_INITF */
+#if defined(RTC_ISR_INITF)
+ if((hrtc->Instance->ISR & RTC_ISR_INITF) == 0U)
+ {
+ /* Set the Initialization mode */
+ hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK;
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC is in INIT state and if Time out is reached exit */
+ while ((hrtc->Instance->ISR & RTC_ISR_INITF) == 0U)
+ {
+ if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+#endif /* RTC_ISR_INITF */
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Convert a 2 digit decimal to BCD format.
+ * @param Value Byte to be converted
+ * @retval Converted byte
+ */
+uint8_t RTC_ByteToBcd2(uint8_t Value)
+{
+ uint32_t bcdhigh = 0U;
+ uint8_t bcdlow = Value;
+
+ while (bcdlow >= 10U)
+ {
+ bcdhigh++;
+ bcdlow -= 10U;
+ }
+
+ return ((uint8_t)(bcdhigh << 4U) | bcdlow);
+}
+
+/**
+ * @brief Convert from 2 digit BCD to Binary.
+ * @param Value BCD value to be converted
+ * @retval Converted word
+ */
+uint8_t RTC_Bcd2ToByte(uint8_t Value)
+{
+ uint8_t tmp;
+ tmp = ((Value & 0xF0U) >> 4U) * 10U;
+ return (tmp + (Value & 0x0FU));
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RTC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_rtc_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rtc_ex.c
new file mode 100644
index 0000000000..2e0bbae94f
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_rtc_ex.c
@@ -0,0 +1,3017 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_rtc_ex.c
+ * @author MCD Application Team
+ * @brief Extended RTC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Real Time Clock (RTC) Extended peripheral:
+ * + RTC Time Stamp functions
+ * + RTC Tamper functions
+ * + RTC Wake-up functions
+ * + Extended Control functions
+ * + Extended RTC features functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (+) Enable the RTC domain access.
+ (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour
+ format using the HAL_RTC_Init() function.
+
+ *** RTC Wakeup configuration ***
+ ================================
+ [..]
+ (+) To configure the RTC Wakeup Clock source and Counter use the HAL_RTCEx_SetWakeUpTimer()
+ function. You can also configure the RTC Wakeup timer with interrupt mode
+ using the HAL_RTCEx_SetWakeUpTimer_IT() function.
+ (+) To read the RTC WakeUp Counter register, use the HAL_RTCEx_GetWakeUpTimer()
+ function.
+
+ *** Outputs configuration ***
+ =============================
+ [..] The RTC has 2 different outputs:
+ (+) RTC_ALARM: this output is used to manage the RTC Alarm A, Alarm B
+ and WaKeUp signals.
+ To output the selected RTC signal, use the HAL_RTC_Init() function.
+ (+) RTC_CALIB: this output is 512Hz signal or 1Hz.
+ To enable the RTC_CALIB, use the HAL_RTCEx_SetCalibrationOutPut() function.
+ (+) Two pins can be used as RTC_ALARM or RTC_CALIB (PC13, PB2) managed on
+ the RTC_OR register.
+ (+) When the RTC_CALIB or RTC_ALARM output is selected, the RTC_OUT pin is
+ automatically configured in output alternate function.
+
+ *** Smooth digital Calibration configuration ***
+ ================================================
+ [..]
+ (+) Configure the RTC Original Digital Calibration Value and the corresponding
+ calibration cycle period (32s,16s and 8s) using the HAL_RTCEx_SetSmoothCalib()
+ function.
+
+ *** TimeStamp configuration ***
+ ===============================
+ [..]
+ (+) Enable the RTC TimeStamp using the HAL_RTCEx_SetTimeStamp() function.
+ You can also configure the RTC TimeStamp with interrupt mode using the
+ HAL_RTCEx_SetTimeStamp_IT() function.
+ (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTCEx_GetTimeStamp()
+ function.
+
+ *** Internal TimeStamp configuration ***
+ ===============================
+ [..]
+ (+) Enable the RTC internal TimeStamp using the HAL_RTCEx_SetInternalTimeStamp() function.
+ User has to check internal timestamp occurrence using __HAL_RTC_INTERNAL_TIMESTAMP_GET_FLAG.
+ (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTCEx_GetTimeStamp()
+ function.
+
+ *** Tamper configuration ***
+ ============================
+ [..]
+ (+) Enable the RTC Tamper and configure the Tamper filter count, trigger Edge
+ or Level according to the Tamper filter (if equal to 0 Edge else Level)
+ value, sampling frequency, NoErase, MaskFlag, precharge or discharge and
+ Pull-UP using the HAL_RTCEx_SetTamper() function. You can configure RTC Tamper
+ with interrupt mode using HAL_RTCEx_SetTamper_IT() function.
+ (+) The default configuration of the Tamper erases the backup registers. To avoid
+ erase, enable the NoErase field on the RTC_TAMPCR register.
+
+ *** Backup Data Registers configuration ***
+ ===========================================
+ [..]
+ (+) To write to the RTC Backup Data registers, use the HAL_RTCEx_BKUPWrite()
+ function.
+ (+) To read the RTC Backup Data registers, use the HAL_RTCEx_BKUPRead()
+ function.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup RTCEx
+ * @brief RTC Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define TAMP_ALL (TAMP_CR1_TAMP1E | TAMP_CR1_TAMP2E | TAMP_CR1_TAMP3E)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup RTCEx_Exported_Functions
+ * @{
+ */
+
+
+/** @addtogroup RTCEx_Exported_Functions_Group1
+ * @brief RTC TimeStamp and Tamper functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC TimeStamp and Tamper functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure TimeStamp feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set TimeStamp.
+ * @note This API must be called before enabling the TimeStamp feature.
+ * @param hrtc RTC handle
+ * @param TimeStampEdge Specifies the pin edge on which the TimeStamp is
+ * activated.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPEDGE_RISING: the Time stamp event occurs on the
+ * rising edge of the related pin.
+ * @arg RTC_TIMESTAMPEDGE_FALLING: the Time stamp event occurs on the
+ * falling edge of the related pin.
+ * @param RTC_TimeStampPin specifies the RTC TimeStamp Pin.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC TimeStamp Pin.
+ * The RTC TimeStamp Pin is per default PC13, but for reasons of
+ * compatibility, this parameter is required.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_TIMESTAMP_EDGE(TimeStampEdge));
+ assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin));
+
+ /* Prevent unused argument(s) compilation warning if no assert_param check */
+ UNUSED(RTC_TimeStampPin);
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Get the RTC_CR register and clear the bits to be configured */
+ tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE));
+
+ tmpreg |= TimeStampEdge;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the Time Stamp TSEDGE and Enable bits */
+ hrtc->Instance->CR = (uint32_t)tmpreg;
+
+ __HAL_RTC_TIMESTAMP_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set TimeStamp with Interrupt.
+ * @note This API must be called before enabling the TimeStamp feature.
+ * @param hrtc RTC handle
+ * @param TimeStampEdge Specifies the pin edge on which the TimeStamp is
+ * activated.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPEDGE_RISING: the Time stamp event occurs on the
+ * rising edge of the related pin.
+ * @arg RTC_TIMESTAMPEDGE_FALLING: the Time stamp event occurs on the
+ * falling edge of the related pin.
+ * @param RTC_TimeStampPin Specifies the RTC TimeStamp Pin.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC TimeStamp Pin.
+ * The RTC TimeStamp Pin is per default PC13, but for reasons of
+ * compatibility, this parameter is required.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp_IT(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_TIMESTAMP_EDGE(TimeStampEdge));
+ assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin));
+
+ /* Prevent unused argument(s) compilation warning if no assert_param check */
+ UNUSED(RTC_TimeStampPin);
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Get the RTC_CR register and clear the bits to be configured */
+ tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE));
+
+ tmpreg |= TimeStampEdge;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the Time Stamp TSEDGE and Enable bits */
+ hrtc->Instance->CR = (uint32_t)tmpreg;
+
+ __HAL_RTC_TIMESTAMP_ENABLE(hrtc);
+
+ /* Enable IT timestamp */
+ __HAL_RTC_TIMESTAMP_ENABLE_IT(hrtc, RTC_IT_TS);
+
+#if !defined(DUAL_CORE)
+ /* RTC timestamp Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+#endif
+
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE();
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate TimeStamp.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tmpreg;
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_TIMESTAMP_DISABLE_IT(hrtc, RTC_IT_TS);
+
+ /* Get the RTC_CR register and clear the bits to be configured */
+ tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE));
+
+ /* Configure the Time Stamp TSEDGE and Enable bits */
+ hrtc->Instance->CR = (uint32_t)tmpreg;
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set Internal TimeStamp.
+ * @note This API must be called before enabling the internal TimeStamp feature.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetInternalTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the internal Time Stamp Enable bits */
+ __HAL_RTC_INTERNAL_TIMESTAMP_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate Internal TimeStamp.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the internal Time Stamp Enable bits */
+ __HAL_RTC_INTERNAL_TIMESTAMP_DISABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the RTC TimeStamp value.
+ * @param hrtc RTC handle
+ * @param sTimeStamp Pointer to Time structure
+ * @param sTimeStampDate Pointer to Date structure
+ * @param Format specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTimeStamp, RTC_DateTypeDef *sTimeStampDate, uint32_t Format)
+{
+ uint32_t tmptime;
+ uint32_t tmpdate;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Get the TimeStamp time and date registers values */
+ tmptime = (uint32_t)(hrtc->Instance->TSTR & RTC_TR_RESERVED_MASK);
+ tmpdate = (uint32_t)(hrtc->Instance->TSDR & RTC_DR_RESERVED_MASK);
+
+ /* Fill the Time structure fields with the read parameters */
+ sTimeStamp->Hours = (uint8_t)((tmptime & (RTC_TSTR_HT | RTC_TSTR_HU)) >> RTC_TSTR_HU_Pos);
+ sTimeStamp->Minutes = (uint8_t)((tmptime & (RTC_TSTR_MNT | RTC_TSTR_MNU)) >> RTC_TSTR_MNU_Pos);
+ sTimeStamp->Seconds = (uint8_t)((tmptime & (RTC_TSTR_ST | RTC_TSTR_SU)) >> RTC_TSTR_SU_Pos);
+ sTimeStamp->TimeFormat = (uint8_t)((tmptime & (RTC_TSTR_PM)) >> RTC_TSTR_PM_Pos);
+ sTimeStamp->SubSeconds = (uint32_t) hrtc->Instance->TSSSR;
+
+ /* Fill the Date structure fields with the read parameters */
+ sTimeStampDate->Year = 0U;
+ sTimeStampDate->Month = (uint8_t)((tmpdate & (RTC_TSDR_MT | RTC_TSDR_MU)) >> RTC_TSDR_MU_Pos);
+ sTimeStampDate->Date = (uint8_t)((tmpdate & (RTC_TSDR_DT | RTC_TSDR_DU)) >> RTC_TSDR_DU_Pos);
+ sTimeStampDate->WeekDay = (uint8_t)((tmpdate & (RTC_TSDR_WDU)) >> RTC_TSDR_WDU_Pos);
+
+ /* Check the input parameters format */
+ if (Format == RTC_FORMAT_BIN)
+ {
+ /* Convert the TimeStamp structure parameters to Binary format */
+ sTimeStamp->Hours = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Hours);
+ sTimeStamp->Minutes = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Minutes);
+ sTimeStamp->Seconds = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Seconds);
+
+ /* Convert the DateTimeStamp structure parameters to Binary format */
+ sTimeStampDate->Month = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Month);
+ sTimeStampDate->Date = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Date);
+ sTimeStampDate->WeekDay = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->WeekDay);
+ }
+
+ /* Clear the TIMESTAMP Flags */
+ __HAL_RTC_INTERNAL_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_ITSF);
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTCEx_Exported_Functions_Group5
+ * @brief Extended RTC Tamper functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Tamper functions #####
+ ==============================================================================
+ [..]
+ (+) Before calling any tamper or internal tamper function, you have to call first
+ HAL_RTC_Init() function.
+ (+) In that ine you can select to output tamper event on RTC pin.
+ [..]
+ (+) Enable the Tamper and configure the Tamper filter count, trigger Edge
+ or Level according to the Tamper filter (if equal to 0 Edge else Level)
+ value, sampling frequency, NoErase, MaskFlag, precharge or discharge and
+ Pull-UP, timestamp using the HAL_RTCEx_SetTamper() function.
+ You can configure Tamper with interrupt mode using HAL_RTCEx_SetTamper_IT() function.
+ (+) The default configuration of the Tamper erases the backup registers. To avoid
+ erase, enable the NoErase field on the TAMP_TAMPCR register.
+ [..]
+ (+) Enable Internal Tamper and configure it with interrupt, timestamp using
+ the HAL_RTCEx_SetInternalTamper() function.
+
+@endverbatim
+* @{
+*/
+
+#if defined(TAMP_CR1_TAMP1E)
+/**
+ * @brief Set Tamper
+ * @param hrtc RTC handle
+ * @param sTamper Pointer to Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDef * sTamper)
+{
+ uint32_t tmpreg;
+
+ /* Point on TAMPER registers base address */
+ TAMP_TypeDef *tamp = (TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET);
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER(sTamper->Tamper));
+ assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase));
+ assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection));
+ assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter));
+ assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency));
+ assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration));
+ assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp));
+ assert_param(IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(sTamper->Filter, sTamper->Trigger));
+
+ /* Configuration register 2 */
+ tmpreg = tamp->CR2;
+ tmpreg &= ~((sTamper->Tamper << TAMP_CR2_TAMP1TRG_Pos) | (sTamper->Tamper << TAMP_CR2_TAMP1MSK_Pos) | (sTamper->Tamper << TAMP_CR2_TAMP1NOERASE_Pos));
+
+ /* Configure the tamper trigger bit */
+ if ((sTamper->Trigger == RTC_TAMPERTRIGGER_HIGHLEVEL) || (sTamper->Trigger == RTC_TAMPERTRIGGER_FALLINGEDGE))
+ {
+ tmpreg |= (sTamper->Tamper << TAMP_CR2_TAMP1TRG_Pos);
+ }
+
+ /* Configure the tamper flags masking bit */
+ if (sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+ tmpreg |= (sTamper->Tamper << TAMP_CR2_TAMP1MSK_Pos);
+ }
+
+ /* Configure the tamper backup registers erasure bit */
+ if (sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
+ {
+ tmpreg |= (sTamper->Tamper << TAMP_CR2_TAMP1NOERASE_Pos);
+ }
+ tamp->CR2 = tmpreg;
+
+ /* Configure filtering parameters */
+ tamp->FLTCR = (sTamper->Filter) | (sTamper->SamplingFrequency) | \
+ (sTamper->PrechargeDuration) | (sTamper->TamperPullUp);
+
+ /* Configure Timestamp saving on tamper detection */
+ if ((hrtc->Instance->CR & RTC_CR_TAMPTS) != (sTamper->TimeStampOnTamperDetection))
+ {
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+ tmpreg = (hrtc->Instance->CR & ~RTC_CR_TAMPTS);
+ hrtc->Instance->CR = (tmpreg | (sTamper->TimeStampOnTamperDetection));
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+ }
+
+ /* Enable selected tamper */
+ tamp->CR1 |= (sTamper->Tamper);
+
+ return HAL_OK;
+}
+#endif /* TAMP_CR1_TAMP1E */
+#if defined (RTC_TAMPCR_TAMP1E)
+/**
+ * @brief Set Tamper.
+ * @note By calling this API we disable the tamper interrupt for all tampers.
+ * @param hrtc RTC handle
+ * @param sTamper Pointer to Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDef * sTamper)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER(sTamper->Tamper));
+ assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase));
+ assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag));
+ assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter));
+ assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency));
+ assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration));
+ assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection));
+ assert_param(IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(sTamper->Filter, sTamper->Trigger));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Copy control register into temporary variable */
+ tmpreg = hrtc->Instance->TAMPCR;
+
+ /* Enable selected tamper */
+ tmpreg |= (sTamper->Tamper);
+
+ /* Configure the bit (located just next to the tamper enable bit) */
+ if ((sTamper->Trigger == RTC_TAMPERTRIGGER_HIGHLEVEL) || (sTamper->Trigger == RTC_TAMPERTRIGGER_FALLINGEDGE))
+ {
+ /* Set the tamper trigger bit */
+ tmpreg |= (uint32_t)(sTamper->Tamper << 1U);
+ }
+ else
+ {
+ /* Clear the tamper trigger bit */
+ tmpreg &= (uint32_t)~(sTamper->Tamper << 1U);
+ }
+
+ /* Configure the tamper backup registers erasure bit */
+ if (sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
+ {
+#if defined(RTC_TAMPCR_TAMP1E)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP1NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP2E)
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP2NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+#if defined(RTC_TAMPCR_TAMP3E)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP3NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+ }
+ else
+ {
+#if defined(RTC_TAMPCR_TAMP1E)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP1NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP2E)
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP2NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+#if defined(RTC_TAMPCR_TAMP3E)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+ }
+
+ /* Configure the tamper flags masking bit */
+ if (sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+#if defined(RTC_TAMPCR_TAMP1E)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP1MF);
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP2E)
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP2MF);
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+#if defined(RTC_TAMPCR_TAMP3E)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP3MF);
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+ }
+ else
+ {
+#if defined(RTC_TAMPCR_TAMP1E)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP1MF);
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP2E)
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP2MF);
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+#if defined(RTC_TAMPCR_TAMP3E)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3MF);
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+ }
+
+ /* Clearing remaining fields before setting them */
+ tmpreg &= ~(RTC_TAMPERFILTER_MASK | RTC_TAMPERSAMPLINGFREQ_RTCCLK_MASK | \
+ RTC_TAMPERPRECHARGEDURATION_MASK | RTC_TAMPER_PULLUP_MASK | \
+ RTC_TIMESTAMPONTAMPERDETECTION_MASK);
+
+ /* Set remaining parameters of desired configuration into temporary variable */
+ tmpreg |= ((uint32_t)sTamper->Filter | \
+ (uint32_t)sTamper->SamplingFrequency | \
+ (uint32_t)sTamper->PrechargeDuration | \
+ (uint32_t)sTamper->TamperPullUp | \
+ (uint32_t)sTamper->TimeStampOnTamperDetection);
+
+ /* Copy desired configuration into configuration register */
+ hrtc->Instance->TAMPCR = tmpreg;
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPCR_TAMP1E */
+
+#if defined(TAMP_CR1_TAMP1E)
+/**
+ * @brief Set Tamper with interrupt.
+ * @param hrtc RTC handle
+ * @param sTamper Pointer to Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDef * sTamper)
+{
+ uint32_t tmpreg;
+
+ /* Point on TAMPER registers base address */
+ TAMP_TypeDef *tamp = (TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET);
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER(sTamper->Tamper));
+ assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase));
+ assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag));
+ assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter));
+ assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency));
+ assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration));
+ assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection));
+ assert_param(IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(sTamper->Filter, sTamper->Trigger));
+
+ /* Copy configuration register into temporary variable */
+ tmpreg = tamp->CR2;
+
+ /* Clear the bits that are going to be configured and leave the others unchanged */
+ tmpreg &= ~((sTamper->Tamper << TAMP_CR2_TAMP1TRG_Pos) | (sTamper->Tamper << TAMP_CR2_TAMP1MSK_Pos) | (sTamper->Tamper << TAMP_CR2_TAMP1NOERASE_Pos));
+
+ /* Configure the tamper trigger bit */
+ if ((sTamper->Trigger == RTC_TAMPERTRIGGER_HIGHLEVEL) || (sTamper->Trigger == RTC_TAMPERTRIGGER_FALLINGEDGE))
+ {
+ tmpreg |= (sTamper->Tamper << TAMP_CR2_TAMP1TRG_Pos);
+ }
+
+ /* Configure the tamper flags masking bit */
+ if (sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+ tmpreg |= (sTamper->Tamper << TAMP_CR2_TAMP1MSK_Pos);
+ }
+
+ /* Configure the tamper backup registers erasure bit */
+ if (sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
+ {
+ tmpreg |= (sTamper->Tamper << TAMP_CR2_TAMP1NOERASE_Pos);
+ }
+ tamp->CR2 = tmpreg;
+
+ /* Configure filtering parameters */
+ tamp->FLTCR = (sTamper->Filter) | (sTamper->SamplingFrequency) | \
+ (sTamper->PrechargeDuration) | (sTamper->TamperPullUp);
+
+ /* Configure Timestamp saving on tamper detection */
+ if ((hrtc->Instance->CR & RTC_CR_TAMPTS) != (sTamper->TimeStampOnTamperDetection))
+ {
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+ tmpreg = (hrtc->Instance->CR & ~RTC_CR_TAMPTS);
+ hrtc->Instance->CR = (tmpreg | (sTamper->TimeStampOnTamperDetection));
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+ }
+
+ /* Configure RTC Tamper Interrupt: EXTI configuration */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_FALLING_EDGE();
+
+ /* Enable interrupt on selected tamper */
+ tamp->IER |= sTamper->Tamper;
+
+ /* Enable selected tamper */
+ tamp->CR1 |= sTamper->Tamper;
+
+ return HAL_OK;
+}
+#endif /* TAMP_CR1_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP1E)
+/**
+ * @brief Set Tamper with interrupt.
+ * @note By calling this API we force the tamper interrupt for all tampers.
+ * @param hrtc RTC handle
+ * @param sTamper Pointer to Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef * hrtc, RTC_TamperTypeDef * sTamper)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER(sTamper->Tamper));
+ assert_param(IS_RTC_TAMPER_INTERRUPT(sTamper->Interrupt));
+ assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase));
+ assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag));
+ assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter));
+ assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency));
+ assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration));
+ assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection));
+ assert_param(IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(sTamper->Filter, sTamper->Trigger));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Copy control register into temporary variable */
+ tmpreg = hrtc->Instance->TAMPCR;
+
+ /* Enable selected tamper */
+ tmpreg |= (sTamper->Tamper);
+
+ /* Configure the tamper trigger bit (located just next to the tamper enable bit) */
+ if ((sTamper->Trigger == RTC_TAMPERTRIGGER_HIGHLEVEL) || (sTamper->Trigger == RTC_TAMPERTRIGGER_FALLINGEDGE))
+ {
+ /* Set the tamper trigger bit */
+ tmpreg |= (uint32_t)(sTamper->Tamper << 1U);
+ }
+ else
+ {
+ /* Clear the tamper trigger bit */
+ tmpreg &= (uint32_t)~(sTamper->Tamper << 1U);
+ }
+
+ /* Configure the tamper backup registers erasure bit */
+ if (sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
+ {
+#if defined(RTC_TAMPCR_TAMP1E)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP1NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP2E)
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP2NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+#if defined(RTC_TAMPCR_TAMP3E)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP3NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+ }
+ else
+ {
+#if defined(RTC_TAMPCR_TAMP1E)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP1NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP2E)
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP2NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+#if defined(RTC_TAMPCR_TAMP3E)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3NOERASE);
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+ }
+
+ /* Configure the tamper flags masking bit */
+ if (sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+#if defined(RTC_TAMPCR_TAMP1E)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP1MF);
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP2E)
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP2MF);
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+#if defined(RTC_TAMPCR_TAMP3E)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP3MF);
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+ }
+ else
+ {
+#if defined(RTC_TAMPCR_TAMP1E)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP1MF);
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP2E)
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP2MF);
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+#if defined(RTC_TAMPCR_TAMP3E)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3MF);
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+ }
+
+ /* Clearing remaining fields before setting them */
+ tmpreg &= ~(RTC_TAMPERFILTER_MASK | RTC_TAMPERSAMPLINGFREQ_RTCCLK_MASK | \
+ RTC_TAMPERPRECHARGEDURATION_MASK | RTC_TAMPER_PULLUP_MASK | \
+ RTC_TIMESTAMPONTAMPERDETECTION_MASK);
+
+ /* Set remaining parameters of desired configuration into temporary variable */
+ tmpreg |= ((uint32_t)sTamper->Filter | \
+ (uint32_t)sTamper->SamplingFrequency | \
+ (uint32_t)sTamper->PrechargeDuration | \
+ (uint32_t)sTamper->TamperPullUp | \
+ (uint32_t)sTamper->TimeStampOnTamperDetection);
+
+ /* Enable interrupt on selected tamper */
+ tmpreg |= (uint32_t)sTamper->Interrupt;
+
+ /* Copy desired configuration into configuration register */
+ hrtc->Instance->TAMPCR = tmpreg;
+
+#if !defined(DUAL_CORE)
+ /* RTC Tamper Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+#endif
+
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE();
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPCR_TAMP1E */
+
+#if defined(TAMP_CR1_TAMP1E)
+/**
+ * @brief Deactivate Tamper.
+ * @param hrtc RTC handle
+ * @param Tamper Selected tamper pin.
+ * This parameter can be a combination of the following values:
+ * @arg RTC_TAMPER_1
+ * @arg RTC_TAMPER_2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef * hrtc, uint32_t Tamper)
+{
+ /* Point on TAMPER registers base address */
+ TAMP_TypeDef *tamp = (TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET);
+
+ assert_param(IS_RTC_TAMPER(Tamper));
+
+ /* Disable the selected Tamper pin */
+ tamp->CR1 &= ~Tamper;
+
+ /* Disable the selected Tamper interrupt */
+ tamp->IER &= ~Tamper;
+
+ /* Clear the selected tamper flags in SR register by setting corresponding bits in SCR register */
+ tamp->SCR = Tamper;
+
+ /* Clear the selected tamper configuration (trigger, mask flag, and no-erase) */
+ tamp->CR2 &= ~((Tamper << TAMP_CR2_TAMP1TRG_Pos) | (Tamper << TAMP_CR2_TAMP1MSK_Pos) | (Tamper << TAMP_CR2_TAMP1NOERASE_Pos));
+
+ return HAL_OK;
+}
+#endif /* TAMP_CR1_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP1E)
+/**
+ * @brief Deactivate Tamper.
+ * @param hrtc RTC handle
+ * @param Tamper Selected tamper pin.
+ * This parameter can be any combination of the following values:
+ * @arg RTC_TAMPER_1
+ * @arg RTC_TAMPER_2
+ * @arg RTC_TAMPER_3
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef * hrtc, uint32_t Tamper)
+{
+ assert_param(IS_RTC_TAMPER(Tamper));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the selected Tamper pin */
+ hrtc->Instance->TAMPCR &= ((uint32_t)~Tamper);
+
+ /* Disable the selected Tamper interrupt */
+#if defined(RTC_TAMPCR_TAMP1E)
+ if ((Tamper & RTC_TAMPER_1) != 0U)
+ {
+ hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP1));
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+#if defined(RTC_TAMPCR_TAMP2E)
+ if ((Tamper & RTC_TAMPER_2) != 0U)
+ {
+ hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP2));
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+#if defined(RTC_TAMPCR_TAMP3E)
+ if ((Tamper & RTC_TAMPER_3) != 0U)
+ {
+ hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP3));
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPCR_TAMP1E */
+
+#if defined(TAMP_CR1_ITAMP1E)
+/**
+ * @brief Set Internal Tamper
+ * @param hrtc RTC handle
+ * @param sIntTamper Pointer to Internal Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetInternalTamper(RTC_HandleTypeDef *hrtc, RTC_InternalTamperTypeDef *sIntTamper)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_INTERNAL_TAMPER(sIntTamper->IntTamper));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sIntTamper->TimeStampOnTamperDetection));
+
+ /* Time-Stamp on internal tamper */
+ if (READ_BIT(RTC->CR, RTC_CR_TAMPTS) != sIntTamper->TimeStampOnTamperDetection)
+ {
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+ MODIFY_REG(RTC->CR, RTC_CR_TAMPTS, sIntTamper->TimeStampOnTamperDetection);
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+ }
+
+ /* Control register 1 */
+ SET_BIT(TAMP->CR1, sIntTamper->IntTamper);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set Internal Tamper in interrupt mode
+ * @param hrtc RTC handle
+ * @param sIntTamper Pointer to Internal Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetInternalTamper_IT(RTC_HandleTypeDef *hrtc, RTC_InternalTamperTypeDef *sIntTamper)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_INTERNAL_TAMPER(sIntTamper->IntTamper));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sIntTamper->TimeStampOnTamperDetection));
+
+ /* Time-stamp on internal tamper */
+ if (READ_BIT(RTC->CR, RTC_CR_TAMPTS) != sIntTamper->TimeStampOnTamperDetection)
+ {
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+ MODIFY_REG(RTC->CR, RTC_CR_TAMPTS, sIntTamper->TimeStampOnTamperDetection);
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+ }
+
+ /* RTC Tamper Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_FALLING_EDGE();
+ /* Interrupt enable register */
+ SET_BIT(TAMP->IER, sIntTamper->IntTamper);
+
+ /* Control register 1 */
+ SET_BIT(TAMP->CR1, sIntTamper->IntTamper);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate Internal Tamper.
+ * @param hrtc RTC handle
+ * @param IntTamper Selected internal tamper event.
+ * This parameter can be any combination of existing internal tampers.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTamper(RTC_HandleTypeDef *hrtc, uint32_t IntTamper)
+{
+ UNUSED(hrtc);
+ assert_param(IS_RTC_INTERNAL_TAMPER(IntTamper));
+
+ /* Disable the selected Tamper pin */
+ CLEAR_BIT(TAMP->CR1, IntTamper);
+
+ /* Clear internal tamper interrupt mode configuration */
+ CLEAR_BIT(TAMP->IER, IntTamper);
+
+ /* Clear internal tamper interrupt */
+ WRITE_REG(TAMP->SCR, IntTamper);
+
+ return HAL_OK;
+}
+#endif /* TAMP_CR1_ITAMP1E */
+
+#if defined(TAMP_ATCR1_TAMP1AM)
+/**
+ * @brief Set all active Tampers at the same time.
+ * @param hrtc RTC handle
+ * @param sAllTamper Pointer to active Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetActiveTampers(RTC_HandleTypeDef *hrtc, RTC_ActiveTampersTypeDef *sAllTamper)
+{
+ uint32_t IER, CR1, CR2, ATCR1, CR, i, tickstart;
+
+#ifdef USE_FULL_ASSERT
+ for (i = 0; i < RTC_TAMP_NB; i++)
+ {
+ assert_param(IS_RTC_TAMPER_ERASE_MODE(sAllTamper->TampInput[i].NoErase));
+ assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sAllTamper->TampInput[i].MaskFlag));
+ /* Mask flag only supported by TAMPER 1, 2 and 3 */
+ assert_param(!((sAllTamper->TampInput[i].MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE) && (i > RTC_TAMPER_3)));
+ }
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sAllTamper->TimeStampOnTamperDetection));
+#endif /* #ifdef USE_FULL_ASSERT */
+
+ /* Active Tampers must not be already enabled */
+ if (READ_BIT(TAMP->ATOR, TAMP_ATOR_INITS) != 0U)
+ {
+ /* Disable all actives tampers with HAL_RTCEx_DeactivateActiveTampers and try again */
+ return HAL_ERROR;
+ }
+
+ /* Set TimeStamp on tamper detection */
+ CR = READ_REG(RTC->CR);
+ if ((CR & RTC_CR_TAMPTS) != (sAllTamper->TimeStampOnTamperDetection))
+ {
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+ MODIFY_REG(RTC->CR, RTC_CR_TAMPTS, sAllTamper->TimeStampOnTamperDetection);
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+ }
+
+ CR1 = READ_REG(TAMP->CR1);
+ CR2 = READ_REG(TAMP->CR2);
+ IER = READ_REG(TAMP->IER);
+
+ /* Set common parameters */
+ ATCR1 = (sAllTamper->ActiveFilter | (sAllTamper->ActiveOutputChangePeriod << TAMP_ATCR1_ATPER_Pos) | sAllTamper->ActiveAsyncPrescaler);
+
+ /* Set specific parameters for each active tamper inputs if enable */
+ for (i = 0; i < RTC_TAMP_NB; i++)
+ {
+ if (sAllTamper->TampInput[i].Enable != RTC_ATAMP_DISABLE)
+ {
+ CR1 |= (TAMP_CR1_TAMP1E << i);
+ ATCR1 |= (TAMP_ATCR1_TAMP1AM << i);
+
+ if (sAllTamper->TampInput[i].Interrupt != RTC_ATAMP_INTERRUPT_DISABLE)
+ {
+ /* RTC Tamper Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE();
+
+ /* Interrupt enable register */
+ IER |= (TAMP_IER_TAMP1IE << i);
+ }
+
+ if (sAllTamper->TampInput[i].MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+ CR2 |= (TAMP_CR2_TAMP1MSK << i);
+ }
+
+ if (sAllTamper->TampInput[i].NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
+ {
+ CR2 |= (TAMP_CR2_TAMP1NOERASE << i);
+ }
+
+ /* Set ATOSHARE and configure ATOSELx[] in case of output sharing */
+ if (sAllTamper->TampInput[i].Output != i)
+ {
+ ATCR1 |= TAMP_ATCR1_ATOSHARE;
+ ATCR1 |= sAllTamper->TampInput[i].Output << ((2u * i) + TAMP_ATCR1_ATOSEL1_Pos);
+ }
+ }
+ }
+
+ WRITE_REG(TAMP->IER, IER);
+ WRITE_REG(TAMP->IER, IER);
+ WRITE_REG(TAMP->ATCR1, ATCR1);
+#if defined(TAMP_ATCR2_ATOSEL1)
+ WRITE_REG(TAMP->ATCR2, ATCR2);
+#endif /* TAMP_ATCR2_ATOSEL1 */
+ WRITE_REG(TAMP->CR2, CR2);
+ WRITE_REG(TAMP->CR1, CR1);
+
+ /* Write seed */
+ for (i = 0; i < RTC_ATAMP_SEED_NB_UINT32; i++)
+ {
+ WRITE_REG(TAMP->ATSEEDR, sAllTamper->Seed[i]);
+ }
+
+ /* Wait till RTC SEEDF flag is set and if Time out is reached exit */
+ tickstart = HAL_GetTick();
+ while (READ_BIT(TAMP->ATOR, TAMP_ATOR_SEEDF) != 0u)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+
+ return HAL_OK;
+}
+#endif /* TAMP_ATCR1_TAMP1AM */
+
+#if defined(TAMP_ATSEEDR_SEED)
+/**
+ * @brief Write a new seed. Active tamper must be enabled.
+ * @param hrtc RTC handle
+ * @param pSeed Pointer to active tamper seed values.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetActiveSeed(RTC_HandleTypeDef *hrtc, uint32_t *pSeed)
+{
+ uint32_t i, tickstart;
+
+ /* Active Tampers must be enabled */
+ if (READ_BIT(TAMP->ATOR, TAMP_ATOR_INITS) == 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ for (i = 0; i < RTC_ATAMP_SEED_NB_UINT32; i++)
+ {
+ WRITE_REG(TAMP->ATSEEDR, pSeed[i]);
+ }
+
+ /* Wait till RTC SEEDF flag is set and if Time out is reached exit */
+ tickstart = HAL_GetTick();
+ while (READ_BIT(TAMP->ATOR, TAMP_ATOR_SEEDF) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+
+ return HAL_OK;
+}
+#endif /* TAMP_ATSEEDR_SEED */
+
+#if defined(TAMP_ATCR1_TAMP1AM)
+/**
+ * @brief Deactivate all Active Tampers at the same time.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateActiveTampers(RTC_HandleTypeDef *hrtc)
+{
+ /* Get Active tampers */
+ uint32_t ATamp_mask = READ_BIT(TAMP->ATCR1, TAMP_ALL);
+
+ UNUSED(hrtc);
+ /* Disable all actives tampers but not passives tampers */
+ CLEAR_BIT(TAMP->CR1, ATamp_mask);
+ /* Disable no erase and mask */
+ CLEAR_BIT(TAMP->CR2, (ATamp_mask | ((ATamp_mask & (TAMP_ATCR1_TAMP1AM | TAMP_ATCR1_TAMP2AM | TAMP_ATCR1_TAMP3AM)) << TAMP_CR2_TAMP1MSK_Pos)));
+
+ /* Clear tamper interrupt and event flags (WO register) of all actives tampers but not passives tampers */
+ WRITE_REG(TAMP->SCR, ATamp_mask);
+
+ /* Clear all active tampers interrupt mode configuration but not passives tampers */
+ CLEAR_BIT(TAMP->IER, ATamp_mask);
+
+ CLEAR_BIT(TAMP->ATCR1, TAMP_ALL | TAMP_ATCR1_ATCKSEL | TAMP_ATCR1_ATPER | \
+ TAMP_ATCR1_ATOSHARE | TAMP_ATCR1_FLTEN);
+
+#if defined(TAMP_ATCR2_ATOSEL1)
+ CLEAR_BIT(TAMP->ATCR2, TAMP_ATCR2_ATOSEL1 | TAMP_ATCR2_ATOSEL2 | TAMP_ATCR2_ATOSEL3 | TAMP_ATCR2_ATOSEL4 |
+ TAMP_ATCR2_ATOSEL5 | TAMP_ATCR2_ATOSEL6 | TAMP_ATCR2_ATOSEL7 | TAMP_ATCR2_ATOSEL8);
+#endif /* TAMP_ATCR2_ATOSEL1 */
+
+ return HAL_OK;
+}
+#endif /* TAMP_ATCR1_TAMP1AM */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTCEx_Exported_Functions_Group1
+ * @brief RTC TimeStamp and Tamper functions
+ *
+* @{
+*/
+
+/**
+ * @brief Handle TimeStamp interrupt request.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+#if defined(RTC_MISR_TSMF)
+void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+
+ /* Point on TAMPER registers base address */
+ TAMP_TypeDef *tamp = (TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET);
+
+ /* Clear the EXTI's Flag for RTC TimeStamp and Tamper */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
+
+ if ((hrtc->Instance->MISR & RTC_MISR_TSMF) != 0u)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call TimeStampEvent registered Callback */
+ hrtc->TimeStampEventCallback(hrtc);
+#else
+ HAL_RTCEx_TimeStampEventCallback(hrtc);
+#endif
+ /* Not immediately clear flags because the content of RTC_TSTR and RTC_TSDR are cleared when TSF bit is reset.*/
+ hrtc->Instance->SCR = RTC_SCR_CTSF;
+ }
+
+ /* Get interrupt status */
+ uint32_t tmp = tamp->MISR;
+
+ /* Immediately clear flags */
+ tamp->SCR = tmp;
+
+#if defined(TAMP_CR1_TAMP1E)
+ /* Check Tamper1 status */
+ if ((tmp & RTC_TAMPER_1) == RTC_TAMPER_1)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Tamper 1 Event registered Callback */
+ hrtc->Tamper1EventCallback(hrtc);
+#else
+ /* Tamper1 callback */
+ HAL_RTCEx_Tamper1EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_TAMP1E */
+
+#if defined(TAMP_CR1_TAMP2E)
+ /* Check Tamper2 status */
+ if ((tmp & RTC_TAMPER_2) == RTC_TAMPER_2)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Tamper 2 Event registered Callback */
+ hrtc->Tamper2EventCallback(hrtc);
+#else
+ /* Tamper2 callback */
+ HAL_RTCEx_Tamper2EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_TAMP2E */
+
+#if defined(TAMP_CR1_TAMP3E)
+ /* Check Tamper3 status */
+ if ((tmp & RTC_TAMPER_3) == RTC_TAMPER_3)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Tamper 3 Event registered Callback */
+ hrtc->Tamper3EventCallback(hrtc);
+#else
+ /* Tamper3 callback */
+ HAL_RTCEx_Tamper3EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_TAMP3E */
+
+#if defined(TAMP_CR1_ITAMP1E)
+ /* Check Internal Tamper status */
+ if ((tmp & RTC_INT_TAMPER_1) == RTC_INT_TAMPER_1)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Internal Tamper Event registered callback */
+ hrtc->InternalTamper1EventCallback(hrtc);
+#else
+ /* Call Internal Tamper Event by-default callback */
+ HAL_RTCEx_InternalTamper1EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_ITAMP1E */
+
+#if defined(TAMP_CR1_ITAMP2E)
+ /* Check Internal Tamper status */
+ if ((tmp & RTC_INT_TAMPER_2) == RTC_INT_TAMPER_2)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Internal Tamper Event registered callback */
+ hrtc->InternalTamper2EventCallback(hrtc);
+#else
+ /* Call Internal Tamper Event by-default callback */
+ HAL_RTCEx_InternalTamper2EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_ITAMP2E */
+
+#if defined(TAMP_CR1_ITAMP3E)
+ /* Check Internal Tamper status */
+ if ((tmp & RTC_INT_TAMPER_3) == RTC_INT_TAMPER_3)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Internal Tamper Event registered callback */
+ hrtc->InternalTamper3EventCallback(hrtc);
+#else
+ /* Call Internal Tamper Event by-default callback */
+ HAL_RTCEx_InternalTamper3EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_ITAMP3E */
+
+#if defined(TAMP_CR1_ITAMP4E)
+ /* Check Internal Tamper status */
+ if ((tmp & RTC_INT_TAMPER_4) == RTC_INT_TAMPER_4)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Internal Tamper Event registered callback */
+ hrtc->InternalTamper4EventCallback(hrtc);
+#else
+ /* Call Internal Tamper Event by-default callback */
+ HAL_RTCEx_InternalTamper4EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_ITAMP4E */
+
+#if defined(TAMP_CR1_ITAMP5E)
+ /* Check Internal Tamper status */
+ if ((tmp & RTC_INT_TAMPER_5) == RTC_INT_TAMPER_5)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Internal Tamper Event registered callback */
+ hrtc->InternalTamper5EventCallback(hrtc);
+#else
+ /* Call Internal Tamper Event by-default callback */
+ HAL_RTCEx_InternalTamper5EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_ITAMP5E */
+
+#if defined(TAMP_CR1_ITAMP6E)
+ /* Check Internal Tamper status */
+ if ((tmp & RTC_INT_TAMPER_6) == RTC_INT_TAMPER_6)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Internal Tamper Event registered callback */
+ hrtc->InternalTamper6EventCallback(hrtc);
+#else
+ /* Call Internal Tamper Event by-default callback */
+ HAL_RTCEx_InternalTamper6EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_ITAMP6E */
+
+#if defined(TAMP_CR1_ITAMP8E)
+ /* Check Internal Tamper status */
+ if ((tmp & RTC_INT_TAMPER_8) == RTC_INT_TAMPER_8)
+ {
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call Internal Tamper Event registered callback */
+ hrtc->InternalTamper8EventCallback(hrtc);
+#else
+ /* Call Internal Tamper Event by-default callback */
+ HAL_RTCEx_InternalTamper8EventCallback(hrtc);
+#endif
+ }
+#endif /* TAMP_CR1_ITAMP8E */
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+#endif /* RTC_MISR_TSMF */
+#if defined(RTC_ISR_TSF)
+void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ /* Clear the EXTI's Flag for RTC TimeStamp and Tamper */
+#if defined(DUAL_CORE)
+ if (HAL_GetCurrentCPUID() == CM7_CPUID)
+ {
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
+ }
+ else
+ {
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTID2_CLEAR_FLAG();
+ }
+#else /* SINGLE_CORE */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
+#endif /* DUAL_CORE */
+
+ /* Get the TimeStamp interrupt source enable status */
+ if (__HAL_RTC_TIMESTAMP_GET_IT_SOURCE(hrtc, RTC_IT_TS) != 0U)
+ {
+ /* Get the pending status of the TIMESTAMP Interrupt */
+ if (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) != 0U)
+ {
+ /* TIMESTAMP callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->TimeStampEventCallback(hrtc);
+#else /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ HAL_RTCEx_TimeStampEventCallback(hrtc);
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+
+ /* Clear the TIMESTAMP interrupt pending bit (this will clear timestamp time and date registers) */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF);
+ }
+ }
+
+#if defined(RTC_TAMPCR_TAMP1E)
+ /* Get the Tamper1 interrupt source enable status */
+ if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP1) != 0U)
+ {
+ /* Get the pending status of the Tamper1 Interrupt */
+ if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != 0U)
+ {
+ /* Clear the Tamper1 interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
+
+ /* Tamper1 callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->Tamper1EventCallback(hrtc);
+#else /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ HAL_RTCEx_Tamper1EventCallback(hrtc);
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ }
+ }
+#endif /* RTC_TAMPCR_TAMP1E */
+
+#if defined(RTC_TAMPCR_TAMP2E)
+ /* Get the Tamper2 interrupt source enable status */
+ if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP2) != 0U)
+ {
+ /* Get the pending status of the Tamper2 Interrupt */
+ if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) != 0U)
+ {
+ /* Clear the Tamper2 interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F);
+
+ /* Tamper2 callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->Tamper2EventCallback(hrtc);
+#else /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ HAL_RTCEx_Tamper2EventCallback(hrtc);
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ }
+ }
+#endif /* RTC_TAMPCR_TAMP2E */
+
+#if defined(RTC_TAMPCR_TAMP3E)
+ /* Get the Tamper3 interrupts source enable status */
+ if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP3) != 0U)
+ {
+ /* Get the pending status of the Tamper3 Interrupt */
+ if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) != 0U)
+ {
+ /* Clear the Tamper3 interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F);
+
+ /* Tamper3 callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->Tamper3EventCallback(hrtc);
+#else /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ HAL_RTCEx_Tamper3EventCallback(hrtc);
+#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS == 1) */
+ }
+ }
+#endif /* RTC_TAMPCR_TAMP3E */
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+#endif /* RTC_ISR_TSF */
+
+/**
+ * @brief TimeStamp callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_TimeStampEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTCEx_Exported_Functions_Group5
+ * @brief Extended RTC Tamper functions
+ *
+* @{
+*/
+
+#if defined(RTC_TAMPER_1)
+/**
+ * @brief Tamper 1 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef * hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper1EventCallback could be implemented in the user file
+ */
+}
+#endif /* RTC_TAMPER_1 */
+
+#if defined(RTC_TAMPER_2)
+/**
+ * @brief Tamper 2 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef * hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper2EventCallback could be implemented in the user file
+ */
+}
+#endif /* RTC_TAMPER_2 */
+
+#if defined(RTC_TAMPER_3)
+/**
+ * @brief Tamper 3 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper3EventCallback(RTC_HandleTypeDef * hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper3EventCallback could be implemented in the user file
+ */
+}
+#endif /* RTC_TAMPER_3 */
+
+/**
+ * @brief Internal Tamper 1 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_InternalTamper1EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_InternalTamper1EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Internal Tamper 2 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_InternalTamper2EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_InternalTamper2EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Internal Tamper 3 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_InternalTamper3EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_InternalTamper3EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Internal Tamper 4 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_InternalTamper4EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_InternalTamper4EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Internal Tamper 5 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_InternalTamper5EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_InternalTamper5EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Internal Tamper 6 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_InternalTamper6EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_InternalTamper6EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Internal Tamper 8 callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_InternalTamper8EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_InternalTamper8EventCallback could be implemented in the user file
+ */
+}
+/**
+ * @}
+ */
+
+/** @addtogroup RTCEx_Exported_Functions_Group1
+ * @brief RTC TimeStamp and Tamper functions
+ *
+* @{
+*/
+
+/**
+ * @brief Handle TimeStamp polling request.
+ * @param hrtc RTC handle
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ while (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) == 0U)
+ {
+ if (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSOVF) != 0U)
+ {
+ /* Clear the TIMESTAMP OverRun Flag */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF);
+
+ /* Change TIMESTAMP state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTCEx_Exported_Functions_Group5
+ * @brief Extended RTC Tamper functions
+ *
+* @{
+*/
+
+#if defined(RTC_TAMPER_1)
+/**
+ * @brief Handle Tamper1 Polling.
+ * @param hrtc RTC handle
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef * hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPER_1 */
+
+#if defined(RTC_TAMPER_2)
+/**
+ * @brief Handle Tamper2 Polling.
+ * @param hrtc RTC handle
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef * hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPER_2 */
+
+#if defined(RTC_TAMPER_3)
+/**
+ * @brief Handle Tamper3 Polling.
+ * @param hrtc RTC handle
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper3Event(RTC_HandleTypeDef * hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPER_3 */
+
+#if defined(TAMP_CR1_ITAMP1E)
+/**
+ * @brief Internal Tamper event polling.
+ * @param hrtc RTC handle
+ * @param IntTamper selected tamper.
+ * This parameter can be any combination of existing internal tampers.
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForInternalTamperEvent(RTC_HandleTypeDef *hrtc, uint32_t IntTamper, uint32_t Timeout)
+{
+ UNUSED(hrtc);
+ assert_param(IS_RTC_INTERNAL_TAMPER(IntTamper));
+
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while (READ_BIT(TAMP->SR, IntTamper) != IntTamper)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ WRITE_REG(TAMP->SCR, IntTamper);
+
+ return HAL_OK;
+}
+#endif /* TAMP_CR1_ITAMP1E */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTCEx_Exported_Functions_Group2
+ * @brief RTC Wake-up functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Wake-up functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Wake-up feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set wake up timer.
+ * @param hrtc RTC handle
+ * @param WakeUpCounter Wake up counter
+ * @param WakeUpClock Wake up clock
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock));
+ assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Check RTC WUTWF flag is reset only when wake up timer enabled */
+ if ((hrtc->Instance->CR & RTC_CR_WUTE) != 0U)
+ {
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is reset and if Time out is reached exit */
+ #if defined(RTC_ICSR_WUTWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_WUTWF) != 0U)
+ #endif /* RTC_ICSR_WUTWF */
+ #if defined(RTC_ISR_WUTWF)
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) != 0U)
+ #endif /* RTC_ISR_WUTWF */
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is set and if Time out is reached exit */
+ #if defined(RTC_ICSR_WUTWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_WUTWF) == 0U)
+ #endif /* RTC_ICSR_WUTWF */
+ #if defined(RTC_ISR_WUTWF)
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == 0U)
+ #endif /* RTC_ISR_WUTWF */
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear the Wakeup Timer clock source bits and configure the clock source in CR register */
+ {
+ uint32_t CR_tmp = hrtc->Instance->CR;
+ CR_tmp &= (uint32_t)~RTC_CR_WUCKSEL;
+ CR_tmp |= (uint32_t)WakeUpClock;
+ hrtc->Instance->CR = CR_tmp;
+ }
+
+ /* Configure the Wakeup Timer counter */
+ hrtc->Instance->WUTR = (uint32_t)WakeUpCounter;
+
+ /* Enable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set wake up timer with interrupt.
+ * @param hrtc RTC handle
+ * @param WakeUpCounter Wake up counter
+ * @param WakeUpClock Wake up clock
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock));
+ assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Check RTC WUTWF flag is reset only when wake up timer enabled */
+ if ((hrtc->Instance->CR & RTC_CR_WUTE) != 0U)
+ {
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is reset and if Time out is reached exit */
+ #if defined(RTC_ICSR_WUTWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_WUTWF) != 0U)
+ #endif /* RTC_ICSR_WUTWF */
+ #if defined(RTC_ISR_WUTWF)
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) != 0U)
+ #endif /* RTC_ISR_WUTWF */
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ /* Disable the Wake-Up timer */
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ /* Clear flag Wake-Up */
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is set and if Time out is reached exit */
+ #if defined(RTC_ICSR_WUTWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_WUTWF) == 0U)
+ #endif /* RTC_ICSR_WUTWF */
+ #if defined(RTC_ISR_WUTWF)
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == 0U)
+ #endif /* RTC_ISR_WUTWF */
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Configure the Wakeup Timer counter */
+ hrtc->Instance->WUTR = (uint32_t)WakeUpCounter;
+
+ /* Clear the Wakeup Timer clock source bits and configure the clock source in CR register */
+ {
+ uint32_t CR_tmp = hrtc->Instance->CR;
+ CR_tmp &= (uint32_t)~RTC_CR_WUCKSEL;
+ CR_tmp |= (uint32_t)WakeUpClock;
+ hrtc->Instance->CR = CR_tmp;
+ }
+
+#if !defined(DUAL_CORE)
+ /* RTC WakeUpTimer Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT();
+#endif
+
+ __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();
+
+ /* Configure the Interrupt in the RTC_CR register */
+ __HAL_RTC_WAKEUPTIMER_ENABLE_IT(hrtc, RTC_IT_WUT);
+
+ /* Enable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate wake up timer counter.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tickstart;
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Disable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_WAKEUPTIMER_DISABLE_IT(hrtc, RTC_IT_WUT);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC WUTWF flag is set and if Time out is reached exit */
+ #if defined(RTC_ICSR_WUTWF)
+ while (READ_BIT(hrtc->Instance->ICSR, RTC_FLAG_WUTWF) == 0U)
+ #endif /* RTC_ICSR_WUTWF */
+ #if defined(RTC_ISR_WUTWF)
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == 0U)
+ #endif /* RTC_ISR_WUTWF */
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get wake up timer counter.
+ * @param hrtc RTC handle
+ * @retval Counter value
+ */
+uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc)
+{
+ /* Get the counter value */
+ return ((uint32_t)(hrtc->Instance->WUTR & RTC_WUTR_WUT));
+}
+
+/**
+ * @brief Handle Wake Up Timer interrupt request.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ /* Clear the EXTI's line Flag for RTC WakeUpTimer */
+#if defined(DUAL_CORE)
+ if (HAL_GetCurrentCPUID() == CM7_CPUID)
+ {
+ __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
+ }
+ else
+ {
+ __HAL_RTC_WAKEUPTIMER_EXTID2_CLEAR_FLAG();
+ }
+#else /* SINGLE_CORE */
+ __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
+#endif /* DUAL_CORE */
+
+#if defined(RTC_MISR_WUTMF)
+ /* Get the pending status of the WAKEUPTIMER Interrupt */
+ if ((hrtc->Instance->MISR & RTC_MISR_WUTMF) != 0u)
+ {
+ /* Immediately clear flags */
+ hrtc->Instance->SCR = RTC_SCR_CWUTF;
+
+ /* WAKEUPTIMER callback */
+ #if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call WakeUpTimerEvent registered Callback */
+ hrtc->WakeUpTimerEventCallback(hrtc);
+ #else
+ HAL_RTCEx_WakeUpTimerEventCallback(hrtc);
+ #endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ }
+#endif /* RTC_MISR_WUTMF */
+#if defined(RTC_ISR_WUTF)
+ /* Get the pending status of the WAKEUPTIMER Interrupt */
+ if (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) != 0U)
+ {
+ /* Clear the WAKEUPTIMER interrupt pending bit */
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
+
+ /* WAKEUPTIMER callback */
+ #if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ /* Call WakeUpTimerEvent registered Callback */
+ hrtc->WakeUpTimerEventCallback(hrtc);
+ #else
+ HAL_RTCEx_WakeUpTimerEventCallback(hrtc);
+ #endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ }
+#endif /* RTC_ISR_WUTF */
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+
+/**
+ * @brief Wake Up Timer callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef * hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_WakeUpTimerEventCallback could be implemented in the user file
+ */
+}
+
+
+/**
+ * @brief Handle Wake Up Timer Polling.
+ * @param hrtc RTC handle
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef * hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the WAKEUPTIMER Flag */
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup RTCEx_Exported_Functions_Group6
+ * @brief Extended RTC Backup register functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended RTC Backup register functions #####
+ ===============================================================================
+ [..]
+ (+) Before calling any tamper or internal tamper function, you have to call first
+ HAL_RTC_Init() function.
+ (+) In that ine you can select to output tamper event on RTC pin.
+ [..]
+ This subsection provides functions allowing to
+ (+) Write a data in a specified RTC Backup data register
+ (+) Read a data in a specified RTC Backup data register
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Write a data in a specified RTC Backup data register.
+ * @param hrtc RTC handle
+ * @param BackupRegister RTC Backup data Register number.
+ * This parameter can be: RTC_BKP_DRx where x can be from 0 to 31 to
+ * specify the register.
+ * @param Data Data to be written in the specified Backup data register.
+ * @retval None
+ */
+void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef * hrtc, uint32_t BackupRegister, uint32_t Data)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_BKP(BackupRegister));
+
+ /* Point on address of first backup register */
+#if defined(TAMP_BKP0R)
+ tmp = (uint32_t) & (((TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET))->BKP0R);
+#endif /* TAMP_BKP0R */
+#if defined(RTC_BKP0R)
+ tmp = (uint32_t) & (hrtc->Instance->BKP0R);
+#endif /* RTC_BKP0R */
+
+ tmp += (BackupRegister * 4U);
+
+ /* Write the specified register */
+ *(__IO uint32_t *)tmp = (uint32_t)Data;
+}
+
+
+/**
+ * @brief Read data from the specified RTC Backup data Register.
+ * @param hrtc RTC handle
+ * @param BackupRegister RTC Backup data Register number.
+ * This parameter can be: RTC_BKP_DRx where x can be from 0 to 31 to
+ * specify the register.
+ * @retval Read value
+ */
+uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef * hrtc, uint32_t BackupRegister)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_BKP(BackupRegister));
+
+ /* Point on address of first backup register */
+#if defined(TAMP_BKP0R)
+ tmp = (uint32_t) & (((TAMP_TypeDef *)((uint32_t)hrtc->Instance + TAMP_OFFSET))->BKP0R);
+#endif /* TAMP_BKP0R */
+#if defined(RTC_BKP0R)
+ tmp = (uint32_t) & (hrtc->Instance->BKP0R);
+#endif /* RTC_BKP0R */
+
+ tmp += (BackupRegister * 4U);
+
+ /* Read the specified register */
+ return (*(__IO uint32_t *)tmp);
+}
+
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup RTCEx_Exported_Functions_Group3
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Write a data in a specified RTC Backup data register
+ (+) Read a data in a specified RTC Backup data register
+ (+) Set the Smooth calibration parameters.
+ (+) Set Low Power calibration parameter (if feature supported).
+ (+) Configure the Synchronization Shift Control Settings.
+ (+) Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ (+) Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ (+) Enable the RTC reference clock detection.
+ (+) Disable the RTC reference clock detection.
+ (+) Enable the Bypass Shadow feature.
+ (+) Disable the Bypass Shadow feature.
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Set the Smooth calibration parameters.
+ * @param hrtc RTC handle
+ * @param SmoothCalibPeriod Select the Smooth Calibration Period.
+ * This parameter can be can be one of the following values :
+ * @arg RTC_SMOOTHCALIB_PERIOD_32SEC: The smooth calibration period is 32s.
+ * @arg RTC_SMOOTHCALIB_PERIOD_16SEC: The smooth calibration period is 16s.
+ * @arg RTC_SMOOTHCALIB_PERIOD_8SEC: The smooth calibration period is 8s.
+ * @param SmoothCalibPlusPulses Select to Set or reset the CALP bit.
+ * This parameter can be one of the following values:
+ * @arg RTC_SMOOTHCALIB_PLUSPULSES_SET: Add one RTCCLK pulse every 2*11 pulses.
+ * @arg RTC_SMOOTHCALIB_PLUSPULSES_RESET: No RTCCLK pulses are added.
+ * @param SmoothCalibMinusPulsesValue Select the value of CALM[8:0] bits.
+ * This parameter can be one any value from 0 to 0x000001FF.
+ * @note To deactivate the smooth calibration, the field SmoothCalibPlusPulses
+ * must be equal to SMOOTHCALIB_PLUSPULSES_RESET and the field
+ * SmoothCalibMinusPulsesValue must be equal to 0.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef * hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmoothCalibMinusPulsesValue)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_SMOOTH_CALIB_PERIOD(SmoothCalibPeriod));
+ assert_param(IS_RTC_SMOOTH_CALIB_PLUS(SmoothCalibPlusPulses));
+ assert_param(IS_RTC_SMOOTH_CALIB_MINUS(SmoothCalibMinusPulsesValue));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* check if a calibration operation is pending */
+#if defined(RTC_ICSR_RECALPF)
+ if ((hrtc->Instance->ICSR & RTC_ICSR_RECALPF) != 0U)
+#endif /* RTC_ICSR_RECALPF */
+#if defined(RTC_ISR_RECALPF)
+ if ((hrtc->Instance->ISR & RTC_ISR_RECALPF) != 0U)
+#endif /* RTC_ISR_RECALPF */
+ {
+ tickstart = HAL_GetTick();
+
+ /* Wait for pending calibration operation to finish */
+#if defined(RTC_ICSR_RECALPF)
+ while ((hrtc->Instance->ICSR & RTC_ICSR_RECALPF) != 0U)
+#endif /* RTC_ICSR_RECALPF */
+#if defined(RTC_ISR_RECALPF)
+ while ((hrtc->Instance->ISR & RTC_ISR_RECALPF) != 0U)
+#endif /* RTC_ISR_RECALPF */
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Configure the Smooth calibration settings */
+ MODIFY_REG(hrtc->Instance->CALR, (RTC_CALR_CALP | RTC_CALR_CALW8 | RTC_CALR_CALW16 | RTC_CALR_CALM), (uint32_t)(SmoothCalibPeriod | SmoothCalibPlusPulses | SmoothCalibMinusPulsesValue));
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the Synchronization Shift Control Settings.
+ * @note When REFCKON is set, firmware must not write to Shift control register.
+ * @param hrtc RTC handle
+ * @param ShiftAdd1S Select to add or not 1 second to the time calendar.
+ * This parameter can be one of the following values:
+ * @arg RTC_SHIFTADD1S_SET: Add one second to the clock calendar.
+ * @arg RTC_SHIFTADD1S_RESET: No effect.
+ * @param ShiftSubFS Select the number of Second Fractions to substitute.
+ * This parameter can be one any value from 0 to 0x7FFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef * hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_SHIFT_ADD1S(ShiftAdd1S));
+ assert_param(IS_RTC_SHIFT_SUBFS(ShiftSubFS));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait until the shift is completed */
+#if defined(RTC_ICSR_SHPF)
+ while ((hrtc->Instance->ICSR & RTC_ICSR_SHPF) != 0U)
+#endif /* RTC_ICSR_SHPF */
+#if defined(RTC_ISR_SHPF)
+ while ((hrtc->Instance->ISR & RTC_ISR_SHPF) != 0U)
+#endif /* RTC_ISR_SHPF */
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check if the reference clock detection is disabled */
+ if ((hrtc->Instance->CR & RTC_CR_REFCKON) == 0U)
+ {
+ /* Configure the Shift settings */
+ hrtc->Instance->SHIFTR = (uint32_t)(uint32_t)(ShiftSubFS) | (uint32_t)(ShiftAdd1S);
+
+ /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if ((hrtc->Instance->CR & RTC_CR_BYPSHAD) == 0U)
+ {
+ if (HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ else
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ * @param hrtc RTC handle
+ * @param CalibOutput Select the Calibration output Selection.
+ * This parameter can be one of the following values:
+ * @arg RTC_CALIBOUTPUT_512HZ: A signal has a regular waveform at 512Hz.
+ * @arg RTC_CALIBOUTPUT_1HZ: A signal has a regular waveform at 1Hz.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef * hrtc, uint32_t CalibOutput)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_CALIB_OUTPUT(CalibOutput));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Clear flags before config */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_COSEL;
+
+ /* Configure the RTC_CR register */
+ hrtc->Instance->CR |= (uint32_t)CalibOutput;
+
+ __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef * hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the RTC reference clock detection.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef * hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if (RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state*/
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ __HAL_RTC_CLOCKREF_DETECTION_ENABLE(hrtc);
+
+ /* Exit Initialization mode */
+#if defined(RTC_ICSR_INIT)
+ hrtc->Instance->ICSR &= (uint32_t)~RTC_ICSR_INIT;
+#endif /* RTC_ICSR_INIT */
+#if defined(RTC_ISR_INIT)
+ hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
+#endif /* RTC_ISR_INIT */
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the RTC reference clock detection.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateRefClock(RTC_HandleTypeDef * hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if (RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state*/
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ __HAL_RTC_CLOCKREF_DETECTION_DISABLE(hrtc);
+
+ /* Exit Initialization mode */
+#if defined(RTC_ICSR_INIT)
+ hrtc->Instance->ICSR &= (uint32_t)~RTC_ICSR_INIT;
+#endif /* RTC_ICSR_INIT */
+#if defined(RTC_ISR_INIT)
+ hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
+#endif /* RTC_ISR_INIT */
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the Bypass Shadow feature.
+ * @note When the Bypass Shadow is enabled the calendar value are taken
+ * directly from the Calendar counter.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef * hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set the BYPSHAD bit */
+ hrtc->Instance->CR |= (uint8_t)RTC_CR_BYPSHAD;
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the Bypass Shadow feature.
+ * @note When the Bypass Shadow is enabled the calendar value are taken
+ * directly from the Calendar counter.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef * hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Reset the BYPSHAD bit */
+ hrtc->Instance->CR &= ((uint8_t)~RTC_CR_BYPSHAD);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+#if defined(TAMP_COUNTR)
+/**
+ * @brief Increment Monotonic counter.
+ * @param hrtc RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_MonotonicCounterIncrement(RTC_HandleTypeDef *hrtc)
+{
+ UNUSED(hrtc);
+ /* This register is read-only only and is incremented by one when a write access is done to this
+ register. This register cannot roll-over and is frozen when reaching the maximum value. */
+ CLEAR_REG(TAMP->COUNTR);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Monotonic counter incrementation.
+ * @param hrtc RTC handle
+ * @param Counter monotonic counter value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_MonotonicCounterGet(RTC_HandleTypeDef *hrtc, uint32_t *Counter)
+{
+ UNUSED(hrtc);
+ /* This register is read-only only and is incremented by one when a write access is done to this
+ register. This register cannot roll-over and is frozen when reaching the maximum value. */
+ *Counter = READ_REG(TAMP->COUNTR);
+
+ return HAL_OK;
+}
+#endif /* TAMP_COUNTR */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTCEx_Exported_Functions_Group4
+ * @brief Extended features functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) RTC Alarm B callback
+ (+) RTC Poll for Alarm B request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Alarm B callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef * hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_AlarmBEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Handle Alarm B Polling request.
+ * @param hrtc RTC handle
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef * hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Alarm Flag */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_sai.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sai.c
new file mode 100644
index 0000000000..a858d8e452
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sai.c
@@ -0,0 +1,2920 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ @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 (surcharged) 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 (surcharged) functions:
+ examples HAL_SAI_RxCpltCallback(), HAL_SAI_ErrorCallback().
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) 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 (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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_FIFO_SIZE 8U
+#define SAI_DEFAULT_TIMEOUT 4U
+#define SAI_LONG_TIMEOUT 1000U
+/**
+ * @}
+ */
+
+/* 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 */
+ /* (freq x 10) to keep Significant digits */
+ tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * hsai->FrameInit.FrameLength);
+ }
+ 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;
+ }
+ }
+
+ /* 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 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;
+ }
+ }
+ }
+
+ /* Disable SAI peripheral */
+ if (SAI_Disable(hsai) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+
+ /* 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);
+
+ /* 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;
+
+ /* Disable SAI peripheral */
+ if (SAI_Disable(hsai) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+
+ /* 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 untill 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 occured ------------------------------------*/
+ 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(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(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)
+{
+ register 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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_sai_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sai_ex.c
new file mode 100644
index 0000000000..fd392896b1
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sai_ex.c
@@ -0,0 +1,135 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 0x77U
+#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(SAI_HandleTypeDef *hsai, 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 */
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_sd.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sd.c
new file mode 100644
index 0000000000..170930a97f
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sd.c
@@ -0,0 +1,3942 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_sd.c
+ * @author MCD Application Team
+ * @brief SD card HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Secure Digital (SD) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver implements a high level communication layer for read and write from/to
+ this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by
+ the user in HAL_SD_MspInit() function (MSP layer).
+ Basically, the MSP layer configuration should be the same as we provide in the
+ examples.
+ You can easily tailor this configuration according to hardware resources.
+
+ [..]
+ This driver is a generic layered driver for SDMMC memories which uses the HAL
+ SDMMC driver functions to interface with SD and uSD cards devices.
+ It is used as follows:
+
+ (#)Initialize the SDMMC low level resources by implementing the HAL_SD_MspInit() API:
+ (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE();
+ (##) SDMMC pins configuration for SD card
+ (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
+ (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
+ and according to your pin assignment;
+ (##) NVIC configuration if you need to use interrupt process (HAL_SD_ReadBlocks_IT()
+ and HAL_SD_WriteBlocks_IT() APIs).
+ (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
+ (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
+ (+++) SDMMC interrupts are managed using the macros __HAL_SD_ENABLE_IT()
+ and __HAL_SD_DISABLE_IT() inside the communication process.
+ (+++) SDMMC interrupts pending bits are managed using the macros __HAL_SD_GET_IT()
+ and __HAL_SD_CLEAR_IT()
+ (##) No general propose DMA Configuration is needed, an Internal DMA for SDMMC Peripheral are used.
+
+ (#) At this stage, you can perform SD read/write/erase operations after SD card initialization
+
+
+ *** SD Card Initialization and configuration ***
+ ================================================
+ [..]
+ To initialize the SD Card, use the HAL_SD_Init() function. It Initializes
+ SDMMC Peripheral(STM32 side) and the SD Card, and put it into StandBy State (Ready for data transfer).
+ This function provide the following operations:
+
+ (#) Apply the SD Card initialization process at 400KHz and check the SD Card
+ type (Standard Capacity or High Capacity). You can change or adapt this
+ frequency by adjusting the "ClockDiv" field.
+ The SD Card frequency (SDMMC_CK) is computed as follows:
+
+ SDMMC_CK = SDMMCCLK / (2 * ClockDiv)
+
+ In initialization mode and according to the SD Card standard,
+ make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
+
+ This phase of initialization is done through SDMMC_Init() and
+ SDMMC_PowerState_ON() SDMMC low level APIs.
+
+ (#) Initialize the SD card. The API used is HAL_SD_InitCard().
+ This phase allows the card initialization and identification
+ and check the SD Card type (Standard Capacity or High Capacity)
+ The initialization flow is compatible with SD standard.
+
+ This API (HAL_SD_InitCard()) could be used also to reinitialize the card in case
+ of plug-off plug-in.
+
+ (#) Configure the SD Card Data transfer frequency. You can change or adapt this
+ frequency by adjusting the "ClockDiv" field.
+ In transfer mode and according to the SD Card standard, make sure that the
+ SDMMC_CK frequency doesn't exceed 25MHz and 100MHz in High-speed mode switch.
+
+ (#) Select the corresponding SD Card according to the address read with the step 2.
+
+ (#) Configure the SD Card in wide bus mode: 4-bits data.
+
+ *** SD Card Read operation ***
+ ==============================
+ [..]
+ (+) You can read from SD card in polling mode by using function HAL_SD_ReadBlocks().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_SD_GetCardState() function for SD card state.
+
+ (+) You can read from SD card in DMA mode by using function HAL_SD_ReadBlocks_DMA().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_SD_GetCardState() function for SD card state.
+ You could also check the DMA transfer process through the SD Rx interrupt event.
+
+ (+) You can read from SD card in Interrupt mode by using function HAL_SD_ReadBlocks_IT().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_SD_GetCardState() function for SD card state.
+ You could also check the IT transfer process through the SD Rx interrupt event.
+
+ *** SD Card Write operation ***
+ ===============================
+ [..]
+ (+) You can write to SD card in polling mode by using function HAL_SD_WriteBlocks().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_SD_GetCardState() function for SD card state.
+
+ (+) You can write to SD card in DMA mode by using function HAL_SD_WriteBlocks_DMA().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_SD_GetCardState() function for SD card state.
+ You could also check the DMA transfer process through the SD Tx interrupt event.
+
+ (+) You can write to SD card in Interrupt mode by using function HAL_SD_WriteBlocks_IT().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to ensure that the transfer is done correctly. The check is done
+ through HAL_SD_GetCardState() function for SD card state.
+ You could also check the IT transfer process through the SD Tx interrupt event.
+
+ *** SD card status ***
+ ======================
+ [..]
+ (+) The SD Status contains status bits that are related to the SD Memory
+ Card proprietary features. To get SD card status use the HAL_SD_GetCardStatus().
+
+ *** SD card information ***
+ ===========================
+ [..]
+ (+) To get SD card information, you can use the function HAL_SD_GetCardInfo().
+ It returns useful information about the SD card such as block size, card type,
+ block number ...
+
+ *** SD card CSD register ***
+ ============================
+ (+) The HAL_SD_GetCardCSD() API allows to get the parameters of the CSD register.
+ Some of the CSD parameters are useful for card initialization and identification.
+
+ *** SD card CID register ***
+ ============================
+ (+) The HAL_SD_GetCardCID() API allows to get the parameters of the CID register.
+ Some of the CSD parameters are useful for card initialization and identification.
+
+ *** SD HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in SD HAL driver.
+
+ (+) __HAL_SD_ENABLE_IT: Enable the SD device interrupt
+ (+) __HAL_SD_DISABLE_IT: Disable the SD device interrupt
+ (+) __HAL_SD_GET_FLAG:Check whether the specified SD flag is set or not
+ (+) __HAL_SD_CLEAR_FLAG: Clear the SD's pending flags
+
+ (@) You can refer to the SD HAL driver header file for more useful macros
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_SD_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ Use Functions @ref HAL_SD_RegisterCallback() to register a user callback,
+ it allows to register following callbacks:
+ (+) TxCpltCallback : callback when a transmission transfer is completed.
+ (+) RxCpltCallback : callback when a reception transfer is completed.
+ (+) ErrorCallback : callback when error occurs.
+ (+) AbortCpltCallback : callback when abort is completed.
+ (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed.
+ (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed.
+ (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed.
+ (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed.
+ (+) MspInitCallback : SD MspInit.
+ (+) MspDeInitCallback : SD MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+ For specific callbacks TransceiverCallback use dedicated register callbacks:
+ respectively @ref HAL_SD_RegisterTransceiverCallback().
+
+ Use function @ref HAL_SD_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function. It allows to reset following callbacks:
+ (+) TxCpltCallback : callback when a transmission transfer is completed.
+ (+) RxCpltCallback : callback when a reception transfer is completed.
+ (+) ErrorCallback : callback when error occurs.
+ (+) AbortCpltCallback : callback when abort is completed.
+ (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed.
+ (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed.
+ (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed.
+ (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed.
+ (+) MspInitCallback : SD MspInit.
+ (+) MspDeInitCallback : SD MspDeInit.
+ This function) takes as parameters the HAL peripheral handle and the Callback ID.
+ For specific callbacks TransceiverCallback use dedicated unregister callbacks:
+ respectively @ref HAL_SD_UnRegisterTransceiverCallback().
+
+ By default, after the @ref HAL_SD_Init and if the state is HAL_SD_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_SD_Init
+ and @ref HAL_SD_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_SD_Init and @ref HAL_SD_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 @ref HAL_SD_RegisterCallback before calling @ref HAL_SD_DeInit
+ or @ref HAL_SD_Init function.
+
+ When The compilation define USE_HAL_SD_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup SD
+ * @{
+ */
+
+#ifdef HAL_SD_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup SD_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+#if defined (DLYB_SDMMC1) && defined (DLYB_SDMMC2)
+#define SD_GET_DLYB_INSTANCE(SDMMC_INSTANCE) (((SDMMC_INSTANCE) == SDMMC1)? \
+ DLYB_SDMMC1 : DLYB_SDMMC2 )
+#elif defined (DLYB_SDMMC1)
+#define SD_GET_DLYB_INSTANCE(SDMMC_INSTANCE) ( DLYB_SDMMC1 )
+#endif
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup SD_Private_Functions SD Private Functions
+ * @{
+ */
+static uint32_t SD_InitCard (SD_HandleTypeDef *hsd);
+static uint32_t SD_PowerON (SD_HandleTypeDef *hsd);
+static uint32_t SD_SendSDStatus (SD_HandleTypeDef *hsd, uint32_t *pSDstatus);
+static uint32_t SD_SendStatus (SD_HandleTypeDef *hsd, uint32_t *pCardStatus);
+static uint32_t SD_WideBus_Enable (SD_HandleTypeDef *hsd);
+static uint32_t SD_WideBus_Disable(SD_HandleTypeDef *hsd);
+static uint32_t SD_FindSCR (SD_HandleTypeDef *hsd, uint32_t *pSCR);
+static void SD_PowerOFF (SD_HandleTypeDef *hsd);
+static void SD_Write_IT (SD_HandleTypeDef *hsd);
+static void SD_Read_IT (SD_HandleTypeDef *hsd);
+static uint32_t SD_HighSpeed (SD_HandleTypeDef *hsd);
+#if (USE_SD_TRANSCEIVER != 0U)
+static uint32_t SD_UltraHighSpeed (SD_HandleTypeDef *hsd);
+static uint32_t SD_DDR_Mode (SD_HandleTypeDef *hsd);
+#endif /* USE_SD_TRANSCEIVER */
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup SD_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup SD_Exported_Functions_Group1
+ * @brief Initialization and de-initialization functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to initialize/de-initialize the SD
+ card device to be ready for use.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the SD according to the specified parameters in the
+ SD_HandleTypeDef and create the associated handle.
+ * @param hsd: Pointer to the SD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_CardStatusTypeDef CardStatus;
+ uint32_t speedgrade, unitsize;
+ uint32_t tickstart;
+
+ /* Check the SD handle allocation */
+ if(hsd == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));
+ assert_param(IS_SDMMC_CLOCK_EDGE(hsd->Init.ClockEdge));
+ assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));
+ assert_param(IS_SDMMC_BUS_WIDE(hsd->Init.BusWide));
+ assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));
+ assert_param(IS_SDMMC_CLKDIV(hsd->Init.ClockDiv));
+
+ if(hsd->State == HAL_SD_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hsd->Lock = HAL_UNLOCKED;
+
+#if (USE_SD_TRANSCEIVER != 0U)
+ /* Force SDMMC_TRANSCEIVER_PRESENT for Legacy usage */
+ if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_UNKNOWN)
+ {
+ hsd->Init.TranceiverPresent = SDMMC_TRANSCEIVER_PRESENT;
+ }
+#endif
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ /* Reset Callback pointers in HAL_SD_STATE_RESET only */
+ hsd->TxCpltCallback = HAL_SD_TxCpltCallback;
+ hsd->RxCpltCallback = HAL_SD_RxCpltCallback;
+ hsd->ErrorCallback = HAL_SD_ErrorCallback;
+ hsd->AbortCpltCallback = HAL_SD_AbortCallback;
+ hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;
+ hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;
+ hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;
+ hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
+#if (USE_SD_TRANSCEIVER != 0U)
+ if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
+ {
+ hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
+ }
+#endif /* USE_SD_TRANSCEIVER */
+
+ if(hsd->MspInitCallback == NULL)
+ {
+ hsd->MspInitCallback = HAL_SD_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hsd->MspInitCallback(hsd);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ HAL_SD_MspInit(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ /* Initialize the Card parameters */
+ if (HAL_SD_InitCard(hsd) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ if( HAL_SD_GetCardStatus(hsd, &CardStatus) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+ /* Get Initial Card Speed from Card Status*/
+ speedgrade = CardStatus.UhsSpeedGrade;
+ unitsize = CardStatus.UhsAllocationUnitSize;
+ if ((hsd->SdCard.CardType == CARD_SDHC_SDXC) && ((speedgrade != 0U) || (unitsize != 0U)))
+ {
+ hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
+ }
+ else
+ {
+ if (hsd->SdCard.CardType == CARD_SDHC_SDXC)
+ {
+ hsd->SdCard.CardSpeed = CARD_HIGH_SPEED;
+ }
+ else
+ {
+ hsd->SdCard.CardSpeed = CARD_NORMAL_SPEED;
+ }
+
+ }
+ /* Configure the bus wide */
+ if(HAL_SD_ConfigWideBusOperation(hsd, hsd->Init.BusWide) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Verify that SD card is ready to use after Initialization */
+ tickstart = HAL_GetTick();
+ while((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))
+ {
+ if((HAL_GetTick()-tickstart) >= SDMMC_DATATIMEOUT)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
+ hsd->State= HAL_SD_STATE_READY;
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Initialize the error code */
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+
+ /* Initialize the SD operation */
+ hsd->Context = SD_CONTEXT_NONE;
+
+ /* Initialize the SD state */
+ hsd->State = HAL_SD_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the SD Card.
+ * @param hsd: Pointer to SD handle
+ * @note This function initializes the SD card. It could be used when a card
+ re-initialization is needed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd)
+{
+ uint32_t errorstate;
+ SD_InitTypeDef Init;
+ uint32_t sdmmc_clk;
+
+ /* Default SDMMC peripheral configuration for SD card initialization */
+ Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
+ Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
+ Init.BusWide = SDMMC_BUS_WIDE_1B;
+ Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
+ Init.ClockDiv = SDMMC_INIT_CLK_DIV;
+
+#if (USE_SD_TRANSCEIVER != 0U)
+ if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
+ {
+ /* Set Transceiver polarity */
+ hsd->Instance->POWER |= SDMMC_POWER_DIRPOL;
+ }
+#elif defined (USE_SD_DIRPOL)
+ /* Set Transceiver polarity */
+ hsd->Instance->POWER |= SDMMC_POWER_DIRPOL;
+#endif /* USE_SD_TRANSCEIVER */
+
+ /* Initialize SDMMC peripheral interface with default configuration */
+ (void)SDMMC_Init(hsd->Instance, Init);
+
+ /* Set Power State to ON */
+ (void)SDMMC_PowerState_ON(hsd->Instance);
+
+ /* wait 74 Cycles: required power up waiting time before starting
+ the SD initialization sequence */
+ sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC)/(2U*SDMMC_INIT_CLK_DIV);
+
+ if(sdmmc_clk != 0U)
+ {
+ HAL_Delay(1U+ (74U*1000U/(sdmmc_clk)));
+ }
+ else
+ {
+ HAL_Delay(2U);
+ }
+
+ /* Identify card operating voltage */
+ errorstate = SD_PowerON(hsd);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->ErrorCode |= errorstate;
+ return HAL_ERROR;
+ }
+
+ /* Card initialization */
+ errorstate = SD_InitCard(hsd);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->ErrorCode |= errorstate;
+ return HAL_ERROR;
+ }
+
+ /* Set Block Size for Card */
+ errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief De-Initializes the SD card.
+ * @param hsd: Pointer to SD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
+{
+ /* Check the SD handle allocation */
+ if(hsd == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+#if (USE_SD_TRANSCEIVER != 0U)
+ /* Desactivate the 1.8V Mode */
+ if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ if(hsd->DriveTransceiver_1_8V_Callback == NULL)
+ {
+ hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
+ }
+ hsd->DriveTransceiver_1_8V_Callback(RESET);
+#else
+ HAL_SD_DriveTransceiver_1_8V_Callback(RESET);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+#endif /* USE_SD_TRANSCEIVER */
+
+ /* Set SD power state to off */
+ SD_PowerOFF(hsd);
+
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ if(hsd->MspDeInitCallback == NULL)
+ {
+ hsd->MspDeInitCallback = HAL_SD_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hsd->MspDeInitCallback(hsd);
+#else
+ /* De-Initialize the MSP layer */
+ HAL_SD_MspDeInit(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+ hsd->State = HAL_SD_STATE_RESET;
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Initializes the SD MSP.
+ * @param hsd: Pointer to SD handle
+ * @retval None
+ */
+__weak void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief De-Initialize SD MSP.
+ * @param hsd: Pointer to SD handle
+ * @retval None
+ */
+__weak void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup SD_Exported_Functions_Group2
+ * @brief Data transfer functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the data
+ transfer from/to SD card.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The Data transfer
+ * is managed by polling mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_SD_GetCardState().
+ * @param hsd: Pointer to SD handle
+ * @param pData: pointer to the buffer that will contain the received data
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Number of SD blocks to read
+ * @param Timeout: Specify timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t count, data, dataremaining;
+ uint32_t add = BlockAdd;
+ uint8_t *tempbuff = pData;
+
+ if(NULL == pData)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+
+ if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0U;
+
+ if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = NumberOfBlocks * BLOCKSIZE;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+ __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
+
+ /* Read block(s) in polling mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
+
+ /* Read Multi Block command */
+ errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
+ }
+ else
+ {
+ hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;
+
+ /* Read Single Block command */
+ errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
+ }
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+
+ /* Poll on SDMMC flags */
+ dataremaining = config.DataLength;
+ while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
+ {
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
+ {
+ /* Read data from SDMMC Rx FIFO */
+ for(count = 0U; count < 8U; count++)
+ {
+ data = SDMMC_ReadFIFO(hsd->Instance);
+ *tempbuff = (uint8_t)(data & 0xFFU);
+ tempbuff++;
+ *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
+ tempbuff++;
+ *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
+ tempbuff++;
+ *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
+ tempbuff++;
+ }
+ dataremaining -= 32U;
+ }
+
+ if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
+ hsd->State= HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_TIMEOUT;
+ }
+ }
+ __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
+
+ /* Send stop transmission command in case of multiblock read */
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
+ {
+ if(hsd->SdCard.CardType != CARD_SECURED)
+ {
+ /* Send stop transmission command */
+ errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Get error state */
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ hsd->State = HAL_SD_STATE_READY;
+
+ return HAL_OK;
+ }
+ else
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Allows to write block(s) to a specified address in a card. The Data
+ * transfer is managed by polling mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_SD_GetCardState().
+ * @param hsd: Pointer to SD handle
+ * @param pData: pointer to the buffer that will contain the data to transmit
+ * @param BlockAdd: Block Address where data will be written
+ * @param NumberOfBlocks: Number of SD blocks to write
+ * @param Timeout: Specify timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t count, data, dataremaining;
+ uint32_t add = BlockAdd;
+ uint8_t *tempbuff = pData;
+
+ if(NULL == pData)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+
+ if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0U;
+
+ if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = NumberOfBlocks * BLOCKSIZE;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+ __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
+
+ /* Write Blocks in Polling mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
+
+ /* Write Multi Block command */
+ errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
+ }
+ else
+ {
+ hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
+
+ /* Write Single Block command */
+ errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
+ }
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+
+ /* Write block(s) in polling mode */
+ dataremaining = config.DataLength;
+ while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
+ {
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
+ {
+ /* Write data to SDMMC Tx FIFO */
+ for(count = 0U; count < 8U; count++)
+ {
+ data = (uint32_t)(*tempbuff);
+ tempbuff++;
+ data |= ((uint32_t)(*tempbuff) << 8U);
+ tempbuff++;
+ data |= ((uint32_t)(*tempbuff) << 16U);
+ tempbuff++;
+ data |= ((uint32_t)(*tempbuff) << 24U);
+ tempbuff++;
+ (void)SDMMC_WriteFIFO(hsd->Instance, &data);
+ }
+ dataremaining -= 32U;
+ }
+
+ if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_TIMEOUT;
+ }
+ }
+ __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
+
+ /* Send stop transmission command in case of multiblock write */
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
+ {
+ if(hsd->SdCard.CardType != CARD_SECURED)
+ {
+ /* Send stop transmission command */
+ errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Get error state */
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ hsd->State = HAL_SD_STATE_READY;
+
+ return HAL_OK;
+ }
+ else
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The Data transfer
+ * is managed in interrupt mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_SD_GetCardState().
+ * @note You could also check the IT transfer process through the SD Rx
+ * interrupt event.
+ * @param hsd: Pointer to SD handle
+ * @param pData: Pointer to the buffer that will contain the received data
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Number of blocks to read.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_ReadBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t add = BlockAdd;
+
+ if(NULL == pData)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+
+ if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0U;
+
+ hsd->pRxBuffPtr = pData;
+ hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
+
+ if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+ __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
+
+ /* Read Blocks in IT mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_IT);
+
+ /* Read Multi Block command */
+ errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
+ }
+ else
+ {
+ hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_IT);
+
+ /* Read Single Block command */
+ errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
+ }
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+
+ __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | SDMMC_FLAG_RXFIFOHF));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Writes block(s) to a specified address in a card. The Data transfer
+ * is managed in interrupt mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_SD_GetCardState().
+ * @note You could also check the IT transfer process through the SD Tx
+ * interrupt event.
+ * @param hsd: Pointer to SD handle
+ * @param pData: Pointer to the buffer that will contain the data to transmit
+ * @param BlockAdd: Block Address where data will be written
+ * @param NumberOfBlocks: Number of blocks to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_WriteBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t add = BlockAdd;
+
+ if(NULL == pData)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+
+ if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0U;
+
+ hsd->pTxBuffPtr = pData;
+ hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
+
+ if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+
+ __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
+
+ /* Write Blocks in Polling mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK| SD_CONTEXT_IT);
+
+ /* Write Multi Block command */
+ errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
+ }
+ else
+ {
+ hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_IT);
+
+ /* Write Single Block command */
+ errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
+ }
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+
+ /* Enable transfer interrupts */
+ __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_FLAG_TXFIFOHE));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The Data transfer
+ * is managed by DMA mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_SD_GetCardState().
+ * @note You could also check the DMA transfer process through the SD Rx
+ * interrupt event.
+ * @param hsd: Pointer SD handle
+ * @param pData: Pointer to the buffer that will contain the received data
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Number of blocks to read.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t add = BlockAdd;
+
+ if(NULL == pData)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+
+ if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0U;
+
+ hsd->pRxBuffPtr = pData;
+ hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
+
+ if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+
+ __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
+ hsd->Instance->IDMABASE0 = (uint32_t) pData ;
+ hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
+
+ /* Read Blocks in DMA mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
+
+ /* Read Multi Block command */
+ errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
+ }
+ else
+ {
+ hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);
+
+ /* Read Single Block command */
+ errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
+ }
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+
+ /* Enable transfer interrupts */
+ __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
+
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Writes block(s) to a specified address in a card. The Data transfer
+ * is managed by DMA mode.
+ * @note This API should be followed by a check on the card state through
+ * HAL_SD_GetCardState().
+ * @note You could also check the DMA transfer process through the SD Tx
+ * interrupt event.
+ * @param hsd: Pointer to SD handle
+ * @param pData: Pointer to the buffer that will contain the data to transmit
+ * @param BlockAdd: Block Address where data will be written
+ * @param NumberOfBlocks: Number of blocks to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t add = BlockAdd;
+
+ if(NULL == pData)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+
+ if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0U;
+
+ hsd->pTxBuffPtr = pData;
+ hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
+
+ if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+
+
+ __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
+
+ hsd->Instance->IDMABASE0 = (uint32_t) pData ;
+ hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
+
+ /* Write Blocks in Polling mode */
+ if(NumberOfBlocks > 1U)
+ {
+ hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
+
+ /* Write Multi Block command */
+ errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
+ }
+ else
+ {
+ hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
+
+ /* Write Single Block command */
+ errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
+ }
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ return HAL_ERROR;
+ }
+
+ /* Enable transfer interrupts */
+ __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Erases the specified memory area of the given SD card.
+ * @note This API should be followed by a check on the card state through
+ * HAL_SD_GetCardState().
+ * @param hsd: Pointer to SD handle
+ * @param BlockStartAdd: Start Block address
+ * @param BlockEndAdd: End Block address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
+{
+ uint32_t errorstate;
+ uint32_t start_add = BlockStartAdd;
+ uint32_t end_add = BlockEndAdd;
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+
+ if(end_add < start_add)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ return HAL_ERROR;
+ }
+
+ if(end_add > (hsd->SdCard.LogBlockNbr))
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ /* Check if the card command class supports erase command */
+ if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
+ hsd->State = HAL_SD_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
+ hsd->State = HAL_SD_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Get start and end block for high capacity cards */
+ if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
+ {
+ start_add *= 512U;
+ end_add *= 512U;
+ }
+
+ /* According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */
+ if(hsd->SdCard.CardType != CARD_SECURED)
+ {
+ /* Send CMD32 SD_ERASE_GRP_START with argument as addr */
+ errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ /* Send CMD33 SD_ERASE_GRP_END with argument as addr */
+ errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+
+ /* Send CMD38 ERASE */
+ errorstate = SDMMC_CmdErase(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ hsd->State = HAL_SD_STATE_READY;
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief This function handles SD card interrupt request.
+ * @param hsd: Pointer to SD handle
+ * @retval None
+ */
+void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd)
+{
+ uint32_t errorstate;
+ uint32_t context = hsd->Context;
+
+ /* Check for SDMMC interrupt flags */
+ if((__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) != RESET) && ((context & SD_CONTEXT_IT) != 0U))
+ {
+ SD_Read_IT(hsd);
+ }
+
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) != RESET)
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DATAEND);
+
+ __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT |\
+ SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR | SDMMC_IT_TXFIFOHE |\
+ SDMMC_IT_RXFIFOHF);
+
+ __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_IDMABTC);
+ __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
+
+ if((context & SD_CONTEXT_IT) != 0U)
+ {
+ if(((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
+ {
+ errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= errorstate;
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->ErrorCallback(hsd);
+#else
+ HAL_SD_ErrorCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->RxCpltCallback(hsd);
+#else
+ HAL_SD_RxCpltCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ else
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->TxCpltCallback(hsd);
+#else
+ HAL_SD_TxCpltCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ }
+ else if((context & SD_CONTEXT_DMA) != 0U)
+ {
+ hsd->Instance->DLEN = 0;
+ hsd->Instance->DCTRL = 0;
+ hsd->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
+
+ /* Stop Transfer for Write Multi blocks or Read Multi blocks */
+ if(((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
+ {
+ errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= errorstate;
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->ErrorCallback(hsd);
+#else
+ HAL_SD_ErrorCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ }
+
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+ if(((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->TxCpltCallback(hsd);
+#else
+ HAL_SD_TxCpltCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->RxCpltCallback(hsd);
+#else
+ HAL_SD_RxCpltCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+
+ else if((__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) != RESET) && ((context & SD_CONTEXT_IT) != 0U))
+ {
+ SD_Write_IT(hsd);
+ }
+
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_RXOVERR | SDMMC_FLAG_TXUNDERR) != RESET)
+ {
+ /* Set Error code */
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_DCRCFAIL) != RESET)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
+ }
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_DTIMEOUT) != RESET)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
+ }
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_RXOVERR) != RESET)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
+ }
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_IT_TXUNDERR) != RESET)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
+ }
+
+ /* Clear All flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ /* Disable all interrupts */
+ __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
+ SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
+
+ __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
+ hsd->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
+ hsd->Instance->CMD |= SDMMC_CMD_CMDSTOP;
+ hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
+ hsd->Instance->CMD &= ~(SDMMC_CMD_CMDSTOP);
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DABORT);
+
+ if((context & SD_CONTEXT_IT) != 0U)
+ {
+ /* Set the SD state to ready to be able to start again the process */
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->Context = SD_CONTEXT_NONE;
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->ErrorCallback(hsd);
+#else
+ HAL_SD_ErrorCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ else if((context & SD_CONTEXT_DMA) != 0U)
+ {
+ if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
+ {
+ /* Disable Internal DMA */
+ __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_IDMABTC);
+ hsd->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
+
+ /* Set the SD state to ready to be able to start again the process */
+ hsd->State = HAL_SD_STATE_READY;
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->ErrorCallback(hsd);
+#else
+ HAL_SD_ErrorCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_IDMABTC) != RESET)
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_IDMABTC);
+ if(READ_BIT(hsd->Instance->IDMACTRL, SDMMC_IDMA_IDMABACT) == 0U)
+ {
+ /* Current buffer is buffer0, Transfer complete for buffer1 */
+ if((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->Write_DMADblBuf1CpltCallback(hsd);
+#else
+ HAL_SDEx_Write_DMADoubleBuf1CpltCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ else /* SD_CONTEXT_READ_MULTIPLE_BLOCK */
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->Read_DMADblBuf1CpltCallback(hsd);
+#else
+ HAL_SDEx_Read_DMADoubleBuf1CpltCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ }
+ else /* SD_DMA_BUFFER1 */
+ {
+ /* Current buffer is buffer1, Transfer complete for buffer0 */
+ if((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->Write_DMADblBuf0CpltCallback(hsd);
+#else
+ HAL_SDEx_Write_DMADoubleBuf0CpltCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ else /* SD_CONTEXT_READ_MULTIPLE_BLOCK */
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->Read_DMADblBuf0CpltCallback(hsd);
+#else
+ HAL_SDEx_Read_DMADoubleBuf0CpltCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief return the SD state
+ * @param hsd: Pointer to sd handle
+ * @retval HAL state
+ */
+HAL_SD_StateTypeDef HAL_SD_GetState(SD_HandleTypeDef *hsd)
+{
+ return hsd->State;
+}
+
+/**
+* @brief Return the SD error code
+* @param hsd : Pointer to a SD_HandleTypeDef structure that contains
+ * the configuration information.
+* @retval SD Error Code
+*/
+uint32_t HAL_SD_GetError(SD_HandleTypeDef *hsd)
+{
+ return hsd->ErrorCode;
+}
+
+/**
+ * @brief Tx Transfer completed callbacks
+ * @param hsd: Pointer to SD handle
+ * @retval None
+ */
+__weak void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_TxCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callbacks
+ * @param hsd: Pointer SD handle
+ * @retval None
+ */
+__weak void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_RxCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief SD error callbacks
+ * @param hsd: Pointer SD handle
+ * @retval None
+ */
+__weak void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_ErrorCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief SD Abort callbacks
+ * @param hsd: Pointer SD handle
+ * @retval None
+ */
+__weak void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_AbortCallback can be implemented in the user file
+ */
+}
+
+#if (USE_SD_TRANSCEIVER != 0U)
+/**
+ * @brief Enable/Disable the SD Transceiver 1.8V Mode Callback.
+ * @param status: Voltage Switch State
+ * @retval None
+ */
+__weak void HAL_SD_DriveTransceiver_1_8V_Callback(FlagStatus status)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(status);
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_EnableTransceiver could be implemented in the user file
+ */
+}
+#endif /* USE_SD_TRANSCEIVER */
+
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+/**
+ * @brief Register a User SD Callback
+ * To be used instead of the weak (surcharged) predefined callback
+ * @param hsd : SD handle
+ * @param CallbackID : ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SD_TX_CPLT_CB_ID SD Tx Complete Callback ID
+ * @arg @ref HAL_SD_RX_CPLT_CB_ID SD Rx Complete Callback ID
+ * @arg @ref HAL_SD_ERROR_CB_ID SD Error Callback ID
+ * @arg @ref HAL_SD_ABORT_CB_ID SD Abort Callback ID
+ * @arg @ref HAL_SD_READ_DMA_DBL_BUF0_CPLT_CB_ID SD DMA Rx Double buffer 0 Callback ID
+ * @arg @ref HAL_SD_READ_DMA_DBL_BUF1_CPLT_CB_ID SD DMA Rx Double buffer 1 Callback ID
+ * @arg @ref HAL_SD_WRITE_DMA_DBL_BUF0_CPLT_CB_ID SD DMA Tx Double buffer 0 Callback ID
+ * @arg @ref HAL_SD_WRITE_DMA_DBL_BUF1_CPLT_CB_ID SD DMA Tx Double buffer 1 Callback ID
+ * @arg @ref HAL_SD_MSP_INIT_CB_ID SD MspInit Callback ID
+ * @arg @ref HAL_SD_MSP_DEINIT_CB_ID SD MspDeInit Callback ID
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SD_RegisterCallback(SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackID, pSD_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hsd);
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SD_TX_CPLT_CB_ID :
+ hsd->TxCpltCallback = pCallback;
+ break;
+ case HAL_SD_RX_CPLT_CB_ID :
+ hsd->RxCpltCallback = pCallback;
+ break;
+ case HAL_SD_ERROR_CB_ID :
+ hsd->ErrorCallback = pCallback;
+ break;
+ case HAL_SD_ABORT_CB_ID :
+ hsd->AbortCpltCallback = pCallback;
+ break;
+ case HAL_SD_READ_DMA_DBL_BUF0_CPLT_CB_ID :
+ hsd->Read_DMADblBuf0CpltCallback = pCallback;
+ break;
+ case HAL_SD_READ_DMA_DBL_BUF1_CPLT_CB_ID :
+ hsd->Read_DMADblBuf1CpltCallback = pCallback;
+ break;
+ case HAL_SD_WRITE_DMA_DBL_BUF0_CPLT_CB_ID :
+ hsd->Write_DMADblBuf0CpltCallback = pCallback;
+ break;
+ case HAL_SD_WRITE_DMA_DBL_BUF1_CPLT_CB_ID :
+ hsd->Write_DMADblBuf1CpltCallback = pCallback;
+ break;
+ case HAL_SD_MSP_INIT_CB_ID :
+ hsd->MspInitCallback = pCallback;
+ break;
+ case HAL_SD_MSP_DEINIT_CB_ID :
+ hsd->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hsd->State == HAL_SD_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SD_MSP_INIT_CB_ID :
+ hsd->MspInitCallback = pCallback;
+ break;
+ case HAL_SD_MSP_DEINIT_CB_ID :
+ hsd->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsd);
+ return status;
+}
+
+/**
+ * @brief Unregister a User SD Callback
+ * SD Callback is redirected to the weak (surcharged) predefined callback
+ * @param hsd : SD handle
+ * @param CallbackID : ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SD_TX_CPLT_CB_ID SD Tx Complete Callback ID
+ * @arg @ref HAL_SD_RX_CPLT_CB_ID SD Rx Complete Callback ID
+ * @arg @ref HAL_SD_ERROR_CB_ID SD Error Callback ID
+ * @arg @ref HAL_SD_ABORT_CB_ID SD Abort Callback ID
+ * @arg @ref HAL_SD_READ_DMA_DBL_BUF0_CPLT_CB_ID SD DMA Rx Double buffer 0 Callback ID
+ * @arg @ref HAL_SD_READ_DMA_DBL_BUF1_CPLT_CB_ID SD DMA Rx Double buffer 1 Callback ID
+ * @arg @ref HAL_SD_WRITE_DMA_DBL_BUF0_CPLT_CB_ID SD DMA Tx Double buffer 0 Callback ID
+ * @arg @ref HAL_SD_WRITE_DMA_DBL_BUF1_CPLT_CB_ID SD DMA Tx Double buffer 1 Callback ID
+ * @arg @ref HAL_SD_MSP_INIT_CB_ID SD MspInit Callback ID
+ * @arg @ref HAL_SD_MSP_DEINIT_CB_ID SD MspDeInit Callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SD_UnRegisterCallback(SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hsd);
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SD_TX_CPLT_CB_ID :
+ hsd->TxCpltCallback = HAL_SD_TxCpltCallback;
+ break;
+ case HAL_SD_RX_CPLT_CB_ID :
+ hsd->RxCpltCallback = HAL_SD_RxCpltCallback;
+ break;
+ case HAL_SD_ERROR_CB_ID :
+ hsd->ErrorCallback = HAL_SD_ErrorCallback;
+ break;
+ case HAL_SD_ABORT_CB_ID :
+ hsd->AbortCpltCallback = HAL_SD_AbortCallback;
+ break;
+ case HAL_SD_READ_DMA_DBL_BUF0_CPLT_CB_ID :
+ hsd->Read_DMADblBuf0CpltCallback = HAL_SDEx_Read_DMADoubleBuf0CpltCallback;
+ break;
+ case HAL_SD_READ_DMA_DBL_BUF1_CPLT_CB_ID :
+ hsd->Read_DMADblBuf1CpltCallback = HAL_SDEx_Read_DMADoubleBuf1CpltCallback;
+ break;
+ case HAL_SD_WRITE_DMA_DBL_BUF0_CPLT_CB_ID :
+ hsd->Write_DMADblBuf0CpltCallback = HAL_SDEx_Write_DMADoubleBuf0CpltCallback;
+ break;
+ case HAL_SD_WRITE_DMA_DBL_BUF1_CPLT_CB_ID :
+ hsd->Write_DMADblBuf1CpltCallback = HAL_SDEx_Write_DMADoubleBuf1CpltCallback;
+ break;
+ case HAL_SD_MSP_INIT_CB_ID :
+ hsd->MspInitCallback = HAL_SD_MspInit;
+ break;
+ case HAL_SD_MSP_DEINIT_CB_ID :
+ hsd->MspDeInitCallback = HAL_SD_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hsd->State == HAL_SD_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SD_MSP_INIT_CB_ID :
+ hsd->MspInitCallback = HAL_SD_MspInit;
+ break;
+ case HAL_SD_MSP_DEINIT_CB_ID :
+ hsd->MspDeInitCallback = HAL_SD_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsd);
+ return status;
+}
+
+#if (USE_SD_TRANSCEIVER != 0U)
+/**
+ * @brief Register a User SD Transceiver Callback
+ * To be used instead of the weak (surcharged) predefined callback
+ * @param hsd : SD handle
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SD_RegisterTransceiverCallback(SD_HandleTypeDef *hsd, pSD_TransceiverCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hsd);
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->DriveTransceiver_1_8V_Callback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsd);
+ return status;
+}
+
+/**
+ * @brief Unregister a User SD Transceiver Callback
+ * SD Callback is redirected to the weak (surcharged) predefined callback
+ * @param hsd : SD handle
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SD_UnRegisterTransceiverCallback(SD_HandleTypeDef *hsd)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hsd);
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
+ }
+ else
+ {
+ /* Update the error code */
+ hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsd);
+ return status;
+}
+#endif /* USE_SD_TRANSCEIVER */
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @addtogroup SD_Exported_Functions_Group3
+ * @brief management functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the SD card
+ operations and get the related information
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns information the information of the card which are stored on
+ * the CID register.
+ * @param hsd: Pointer to SD handle
+ * @param pCID: Pointer to a HAL_SD_CardCIDTypeDef structure that
+ * contains all CID register parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_GetCardCID(SD_HandleTypeDef *hsd, HAL_SD_CardCIDTypeDef *pCID)
+{
+ pCID->ManufacturerID = (uint8_t)((hsd->CID[0] & 0xFF000000U) >> 24U);
+
+ pCID->OEM_AppliID = (uint16_t)((hsd->CID[0] & 0x00FFFF00U) >> 8U);
+
+ pCID->ProdName1 = (((hsd->CID[0] & 0x000000FFU) << 24U) | ((hsd->CID[1] & 0xFFFFFF00U) >> 8U));
+
+ pCID->ProdName2 = (uint8_t)(hsd->CID[1] & 0x000000FFU);
+
+ pCID->ProdRev = (uint8_t)((hsd->CID[2] & 0xFF000000U) >> 24U);
+
+ pCID->ProdSN = (((hsd->CID[2] & 0x00FFFFFFU) << 8U) | ((hsd->CID[3] & 0xFF000000U) >> 24U));
+
+ pCID->Reserved1 = (uint8_t)((hsd->CID[3] & 0x00F00000U) >> 20U);
+
+ pCID->ManufactDate = (uint16_t)((hsd->CID[3] & 0x000FFF00U) >> 8U);
+
+ pCID->CID_CRC = (uint8_t)((hsd->CID[3] & 0x000000FEU) >> 1U);
+
+ pCID->Reserved2 = 1U;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Returns information the information of the card which are stored on
+ * the CSD register.
+ * @param hsd: Pointer to SD handle
+ * @param pCSD: Pointer to a HAL_SD_CardCSDTypeDef structure that
+ * contains all CSD register parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_GetCardCSD(SD_HandleTypeDef *hsd, HAL_SD_CardCSDTypeDef *pCSD)
+{
+ pCSD->CSDStruct = (uint8_t)((hsd->CSD[0] & 0xC0000000U) >> 30U);
+
+ pCSD->SysSpecVersion = (uint8_t)((hsd->CSD[0] & 0x3C000000U) >> 26U);
+
+ pCSD->Reserved1 = (uint8_t)((hsd->CSD[0] & 0x03000000U) >> 24U);
+
+ pCSD->TAAC = (uint8_t)((hsd->CSD[0] & 0x00FF0000U) >> 16U);
+
+ pCSD->NSAC = (uint8_t)((hsd->CSD[0] & 0x0000FF00U) >> 8U);
+
+ pCSD->MaxBusClkFrec = (uint8_t)(hsd->CSD[0] & 0x000000FFU);
+
+ pCSD->CardComdClasses = (uint16_t)((hsd->CSD[1] & 0xFFF00000U) >> 20U);
+
+ pCSD->RdBlockLen = (uint8_t)((hsd->CSD[1] & 0x000F0000U) >> 16U);
+
+ pCSD->PartBlockRead = (uint8_t)((hsd->CSD[1] & 0x00008000U) >> 15U);
+
+ pCSD->WrBlockMisalign = (uint8_t)((hsd->CSD[1] & 0x00004000U) >> 14U);
+
+ pCSD->RdBlockMisalign = (uint8_t)((hsd->CSD[1] & 0x00002000U) >> 13U);
+
+ pCSD->DSRImpl = (uint8_t)((hsd->CSD[1] & 0x00001000U) >> 12U);
+
+ pCSD->Reserved2 = 0U; /*!< Reserved */
+
+ if(hsd->SdCard.CardType == CARD_SDSC)
+ {
+ pCSD->DeviceSize = (((hsd->CSD[1] & 0x000003FFU) << 2U) | ((hsd->CSD[2] & 0xC0000000U) >> 30U));
+
+ pCSD->MaxRdCurrentVDDMin = (uint8_t)((hsd->CSD[2] & 0x38000000U) >> 27U);
+
+ pCSD->MaxRdCurrentVDDMax = (uint8_t)((hsd->CSD[2] & 0x07000000U) >> 24U);
+
+ pCSD->MaxWrCurrentVDDMin = (uint8_t)((hsd->CSD[2] & 0x00E00000U) >> 21U);
+
+ pCSD->MaxWrCurrentVDDMax = (uint8_t)((hsd->CSD[2] & 0x001C0000U) >> 18U);
+
+ pCSD->DeviceSizeMul = (uint8_t)((hsd->CSD[2] & 0x00038000U) >> 15U);
+
+ hsd->SdCard.BlockNbr = (pCSD->DeviceSize + 1U) ;
+ hsd->SdCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
+ hsd->SdCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
+
+ hsd->SdCard.LogBlockNbr = (hsd->SdCard.BlockNbr) * ((hsd->SdCard.BlockSize) / 512U);
+ hsd->SdCard.LogBlockSize = 512U;
+ }
+ else if(hsd->SdCard.CardType == CARD_SDHC_SDXC)
+ {
+ /* Byte 7 */
+ pCSD->DeviceSize = (((hsd->CSD[1] & 0x0000003FU) << 16U) | ((hsd->CSD[2] & 0xFFFF0000U) >> 16U));
+
+ hsd->SdCard.BlockNbr = ((pCSD->DeviceSize + 1U) * 1024U);
+ hsd->SdCard.LogBlockNbr = hsd->SdCard.BlockNbr;
+ hsd->SdCard.BlockSize = 512U;
+ hsd->SdCard.LogBlockSize = hsd->SdCard.BlockSize;
+ }
+ else
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ hsd->State = HAL_SD_STATE_READY;
+ return HAL_ERROR;
+ }
+
+ pCSD->EraseGrSize = (uint8_t)((hsd->CSD[2] & 0x00004000U) >> 14U);
+
+ pCSD->EraseGrMul = (uint8_t)((hsd->CSD[2] & 0x00003F80U) >> 7U);
+
+ pCSD->WrProtectGrSize = (uint8_t)(hsd->CSD[2] & 0x0000007FU);
+
+ pCSD->WrProtectGrEnable = (uint8_t)((hsd->CSD[3] & 0x80000000U) >> 31U);
+
+ pCSD->ManDeflECC = (uint8_t)((hsd->CSD[3] & 0x60000000U) >> 29U);
+
+ pCSD->WrSpeedFact = (uint8_t)((hsd->CSD[3] & 0x1C000000U) >> 26U);
+
+ pCSD->MaxWrBlockLen= (uint8_t)((hsd->CSD[3] & 0x03C00000U) >> 22U);
+
+ pCSD->WriteBlockPaPartial = (uint8_t)((hsd->CSD[3] & 0x00200000U) >> 21U);
+
+ pCSD->Reserved3 = 0;
+
+ pCSD->ContentProtectAppli = (uint8_t)((hsd->CSD[3] & 0x00010000U) >> 16U);
+
+ pCSD->FileFormatGroup = (uint8_t)((hsd->CSD[3] & 0x00008000U) >> 15U);
+
+ pCSD->CopyFlag = (uint8_t)((hsd->CSD[3] & 0x00004000U) >> 14U);
+
+ pCSD->PermWrProtect = (uint8_t)((hsd->CSD[3] & 0x00002000U) >> 13U);
+
+ pCSD->TempWrProtect = (uint8_t)((hsd->CSD[3] & 0x00001000U) >> 12U);
+
+ pCSD->FileFormat = (uint8_t)((hsd->CSD[3] & 0x00000C00U) >> 10U);
+
+ pCSD->ECC= (uint8_t)((hsd->CSD[3] & 0x00000300U) >> 8U);
+
+ pCSD->CSD_CRC = (uint8_t)((hsd->CSD[3] & 0x000000FEU) >> 1U);
+
+ pCSD->Reserved4 = 1;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Gets the SD status info.
+ * @param hsd: Pointer to SD handle
+ * @param pStatus: Pointer to the HAL_SD_CardStatusTypeDef structure that
+ * will contain the SD card status information
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypeDef *pStatus)
+{
+ uint32_t sd_status[16];
+ uint32_t errorstate;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ errorstate = SD_SendSDStatus(hsd, sd_status);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ status = HAL_ERROR;
+ }
+ else
+ {
+ pStatus->DataBusWidth = (uint8_t)((sd_status[0] & 0xC0U) >> 6U);
+
+ pStatus->SecuredMode = (uint8_t)((sd_status[0] & 0x20U) >> 5U);
+
+ pStatus->CardType = (uint16_t)(((sd_status[0] & 0x00FF0000U) >> 8U) | ((sd_status[0] & 0xFF000000U) >> 24U));
+
+ pStatus->ProtectedAreaSize = (((sd_status[1] & 0xFFU) << 24U) | ((sd_status[1] & 0xFF00U) << 8U) |
+ ((sd_status[1] & 0xFF0000U) >> 8U) | ((sd_status[1] & 0xFF000000U) >> 24U));
+
+ pStatus->SpeedClass = (uint8_t)(sd_status[2] & 0xFFU);
+
+ pStatus->PerformanceMove = (uint8_t)((sd_status[2] & 0xFF00U) >> 8U);
+
+ pStatus->AllocationUnitSize = (uint8_t)((sd_status[2] & 0xF00000U) >> 20U);
+
+ pStatus->EraseSize = (uint16_t)(((sd_status[2] & 0xFF000000U) >> 16U) | (sd_status[3] & 0xFFU));
+
+ pStatus->EraseTimeout = (uint8_t)((sd_status[3] & 0xFC00U) >> 10U);
+
+ pStatus->EraseOffset = (uint8_t)((sd_status[3] & 0x0300U) >> 8U);
+
+ pStatus->UhsSpeedGrade = (uint8_t)((sd_status[3] & 0x00F0U) >> 4U);
+ pStatus->UhsAllocationUnitSize = (uint8_t)(sd_status[3] & 0x000FU) ;
+ pStatus->VideoSpeedClass = (uint8_t)((sd_status[4] & 0xFF000000U) >> 24U);
+ }
+
+ /* Set Block Size for Card */
+ errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode = errorstate;
+ hsd->State = HAL_SD_STATE_READY;
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Gets the SD card info.
+ * @param hsd: Pointer to SD handle
+ * @param pCardInfo: Pointer to the HAL_SD_CardInfoTypeDef structure that
+ * will contain the SD card status information
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_GetCardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypeDef *pCardInfo)
+{
+ pCardInfo->CardType = (uint32_t)(hsd->SdCard.CardType);
+ pCardInfo->CardVersion = (uint32_t)(hsd->SdCard.CardVersion);
+ pCardInfo->Class = (uint32_t)(hsd->SdCard.Class);
+ pCardInfo->RelCardAdd = (uint32_t)(hsd->SdCard.RelCardAdd);
+ pCardInfo->BlockNbr = (uint32_t)(hsd->SdCard.BlockNbr);
+ pCardInfo->BlockSize = (uint32_t)(hsd->SdCard.BlockSize);
+ pCardInfo->LogBlockNbr = (uint32_t)(hsd->SdCard.LogBlockNbr);
+ pCardInfo->LogBlockSize = (uint32_t)(hsd->SdCard.LogBlockSize);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables wide bus operation for the requested card if supported by
+ * card.
+ * @param hsd: Pointer to SD handle
+ * @param WideMode: Specifies the SD card wide bus mode
+ * This parameter can be one of the following values:
+ * @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer
+ * @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer
+ * @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode)
+{
+ SDMMC_InitTypeDef Init;
+ uint32_t errorstate;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_BUS_WIDE(WideMode));
+
+ /* Change State */
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ if(hsd->SdCard.CardType != CARD_SECURED)
+ {
+ if(WideMode == SDMMC_BUS_WIDE_8B)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ }
+ else if(WideMode == SDMMC_BUS_WIDE_4B)
+ {
+ errorstate = SD_WideBus_Enable(hsd);
+
+ hsd->ErrorCode |= errorstate;
+ }
+ else if(WideMode == SDMMC_BUS_WIDE_1B)
+ {
+ errorstate = SD_WideBus_Disable(hsd);
+
+ hsd->ErrorCode |= errorstate;
+ }
+ else
+ {
+ /* WideMode is not a valid argument*/
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ }
+ }
+ else
+ {
+ /* MMC Card does not support this feature */
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ }
+
+ if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Configure the SDMMC peripheral */
+ Init.ClockEdge = hsd->Init.ClockEdge;
+ Init.ClockPowerSave = hsd->Init.ClockPowerSave;
+ Init.BusWide = WideMode;
+ Init.HardwareFlowControl = hsd->Init.HardwareFlowControl;
+
+ /* Check if user Clock div < Normal speed 25Mhz, no change in Clockdiv */
+ if(hsd->Init.ClockDiv >= SDMMC_NSpeed_CLK_DIV)
+ {
+ Init.ClockDiv = hsd->Init.ClockDiv;
+ }
+ else if (hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)
+ {
+ /* UltraHigh speed SD card,user Clock div */
+ Init.ClockDiv = hsd->Init.ClockDiv;
+ }
+ else if (hsd->SdCard.CardSpeed == CARD_HIGH_SPEED)
+ {
+ /* High speed SD card, Max Frequency = 50Mhz */
+ Init.ClockDiv = SDMMC_HSpeed_CLK_DIV;
+ }
+ else
+ {
+ /* No High speed SD card, Max Frequency = 25Mhz */
+ Init.ClockDiv = SDMMC_NSpeed_CLK_DIV;
+ }
+
+ (void)SDMMC_Init(hsd->Instance, Init);
+ }
+
+ /* Set Block Size for Card */
+ errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ status = HAL_ERROR;
+ }
+
+ /* Change State */
+ hsd->State = HAL_SD_STATE_READY;
+
+ return status;
+}
+
+/**
+ * @brief Configure the speed bus mode
+ * @param hsd: Pointer to the SD handle
+ * @param SpeedMode: Specifies the SD card speed bus mode
+ * This parameter can be one of the following values:
+ * @arg SDMMC_SPEED_MODE_AUTO: Max speed mode supported by the card
+ * @arg SDMMC_SPEED_MODE_DEFAULT: Default Speed/SDR12 mode
+ * @arg SDMMC_SPEED_MODE_HIGH: High Speed/SDR25 mode
+ * @arg SDMMC_SPEED_MODE_ULTRA: Ultra high speed mode
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_SD_ConfigSpeedBusOperation(SD_HandleTypeDef *hsd, uint32_t SpeedMode)
+{
+ uint32_t tickstart;
+ uint32_t errorstate;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_SPEED_MODE(SpeedMode));
+ /* Change State */
+ hsd->State = HAL_SD_STATE_BUSY;
+
+#if (USE_SD_TRANSCEIVER != 0U)
+ if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
+ {
+ switch (SpeedMode)
+ {
+ case SDMMC_SPEED_MODE_AUTO:
+ {
+ if ((hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED) ||
+ (hsd->SdCard.CardType == CARD_SDHC_SDXC))
+ {
+ hsd->Instance->CLKCR |= SDMMC_CLKCR_BUSSPEED;
+ /* Enable Ultra High Speed */
+ if (SD_UltraHighSpeed(hsd) != HAL_SD_ERROR_NONE)
+ {
+ if (SD_HighSpeed(hsd) != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ }
+ }
+ else if (hsd->SdCard.CardSpeed == CARD_HIGH_SPEED)
+ {
+ /* Enable High Speed */
+ if (SD_HighSpeed(hsd) != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ /*Nothing to do, Use defaultSpeed */
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_ULTRA:
+ {
+ if ((hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED) ||
+ (hsd->SdCard.CardType == CARD_SDHC_SDXC))
+ {
+ /* Enable UltraHigh Speed */
+ if (SD_UltraHighSpeed(hsd) != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ hsd->Instance->CLKCR |= SDMMC_CLKCR_BUSSPEED;
+ }
+ else
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_DDR:
+ {
+ if ((hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED) ||
+ (hsd->SdCard.CardType == CARD_SDHC_SDXC))
+ {
+ /* Enable DDR Mode*/
+ if (SD_DDR_Mode(hsd) != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ hsd->Instance->CLKCR |= SDMMC_CLKCR_BUSSPEED | SDMMC_CLKCR_DDR;
+ }
+ else
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_HIGH:
+ {
+ if ((hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED) ||
+ (hsd->SdCard.CardSpeed == CARD_HIGH_SPEED) ||
+ (hsd->SdCard.CardType == CARD_SDHC_SDXC))
+ {
+ /* Enable High Speed */
+ if (SD_HighSpeed(hsd) != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_DEFAULT:
+ break;
+ default:
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ switch (SpeedMode)
+ {
+ case SDMMC_SPEED_MODE_AUTO:
+ {
+ if ((hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED) ||
+ (hsd->SdCard.CardSpeed == CARD_HIGH_SPEED) ||
+ (hsd->SdCard.CardType == CARD_SDHC_SDXC))
+ {
+ /* Enable High Speed */
+ if (SD_HighSpeed(hsd) != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ /*Nothing to do, Use defaultSpeed */
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_HIGH:
+ {
+ if ((hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED) ||
+ (hsd->SdCard.CardSpeed == CARD_HIGH_SPEED) ||
+ (hsd->SdCard.CardType == CARD_SDHC_SDXC))
+ {
+ /* Enable High Speed */
+ if (SD_HighSpeed(hsd) != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_DEFAULT:
+ break;
+ case SDMMC_SPEED_MODE_ULTRA: /*not valid without transceiver*/
+ default:
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ status = HAL_ERROR;
+ break;
+ }
+ }
+#else
+ switch (SpeedMode)
+ {
+ case SDMMC_SPEED_MODE_AUTO:
+ {
+ if ((hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED) ||
+ (hsd->SdCard.CardSpeed == CARD_HIGH_SPEED) ||
+ (hsd->SdCard.CardType == CARD_SDHC_SDXC))
+ {
+ /* Enable High Speed */
+ if (SD_HighSpeed(hsd) != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ /*Nothing to do, Use defaultSpeed */
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_HIGH:
+ {
+ if ((hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED) ||
+ (hsd->SdCard.CardSpeed == CARD_HIGH_SPEED) ||
+ (hsd->SdCard.CardType == CARD_SDHC_SDXC))
+ {
+ /* Enable High Speed */
+ if (SD_HighSpeed(hsd) != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ status = HAL_ERROR;
+ }
+ break;
+ }
+ case SDMMC_SPEED_MODE_DEFAULT:
+ break;
+ case SDMMC_SPEED_MODE_ULTRA: /*not valid without transceiver*/
+ default:
+ hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
+ status = HAL_ERROR;
+ break;
+ }
+#endif /* USE_SD_TRANSCEIVER */
+
+ /* Verify that SD card is ready to use after Speed mode switch*/
+ tickstart = HAL_GetTick();
+ while ((HAL_SD_GetCardState(hsd) != HAL_SD_CARD_TRANSFER))
+ {
+ if ((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
+ hsd->State = HAL_SD_STATE_READY;
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set Block Size for Card */
+ errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+ hsd->ErrorCode |= errorstate;
+ status = HAL_ERROR;
+ }
+
+ /* Change State */
+ hsd->State = HAL_SD_STATE_READY;
+ return status;
+}
+
+/**
+ * @brief Gets the current sd card data state.
+ * @param hsd: pointer to SD handle
+ * @retval Card state
+ */
+HAL_SD_CardStateTypeDef HAL_SD_GetCardState(SD_HandleTypeDef *hsd)
+{
+ uint32_t cardstate;
+ uint32_t errorstate;
+ uint32_t resp1 = 0;
+
+ errorstate = SD_SendStatus(hsd, &resp1);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= errorstate;
+ }
+
+ cardstate = ((resp1 >> 9U) & 0x0FU);
+
+ return (HAL_SD_CardStateTypeDef)cardstate;
+}
+
+/**
+ * @brief Abort the current transfer and disable the SD.
+ * @param hsd: pointer to a SD_HandleTypeDef structure that contains
+ * the configuration information for SD module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_Abort(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_CardStateTypeDef CardState;
+
+ /* DIsable All interrupts */
+ __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
+ SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
+
+ /* Clear All flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ /* If IDMA Context, disable Internal DMA */
+ hsd->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
+
+ hsd->State = HAL_SD_STATE_READY;
+
+ /* Initialize the SD operation */
+ hsd->Context = SD_CONTEXT_NONE;
+
+ CardState = HAL_SD_GetCardState(hsd);
+ if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
+ {
+ hsd->ErrorCode = SDMMC_CmdStopTransfer(hsd->Instance);
+ }
+ if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort the current transfer and disable the SD (IT mode).
+ * @param hsd: pointer to a SD_HandleTypeDef structure that contains
+ * the configuration information for SD module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_Abort_IT(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_CardStateTypeDef CardState;
+
+ /* Disable All interrupts */
+ __HAL_SD_DISABLE_IT(hsd, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
+ SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
+
+ /* If IDMA Context, disable Internal DMA */
+ hsd->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
+
+ /* Clear All flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ CardState = HAL_SD_GetCardState(hsd);
+ hsd->State = HAL_SD_STATE_READY;
+
+ if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
+ {
+ hsd->ErrorCode = SDMMC_CmdStopTransfer(hsd->Instance);
+ }
+
+ if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->AbortCpltCallback(hsd);
+#else
+ HAL_SD_AbortCallback(hsd);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private function ----------------------------------------------------------*/
+/** @addtogroup SD_Private_Functions
+ * @{
+ */
+
+
+/**
+ * @brief Initializes the sd card.
+ * @param hsd: Pointer to SD handle
+ * @retval SD Card error state
+ */
+static uint32_t SD_InitCard(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_CardCSDTypeDef CSD;
+ uint32_t errorstate;
+ uint16_t sd_rca = 1U;
+
+ /* Check the power State */
+ if(SDMMC_GetPowerState(hsd->Instance) == 0U)
+ {
+ /* Power off */
+ return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
+ }
+
+ if(hsd->SdCard.CardType != CARD_SECURED)
+ {
+ /* Send CMD2 ALL_SEND_CID */
+ errorstate = SDMMC_CmdSendCID(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+ else
+ {
+ /* Get Card identification number data */
+ hsd->CID[0U] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+ hsd->CID[1U] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP2);
+ hsd->CID[2U] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP3);
+ hsd->CID[3U] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP4);
+ }
+ }
+
+ if(hsd->SdCard.CardType != CARD_SECURED)
+ {
+ /* Send CMD3 SET_REL_ADDR with argument 0 */
+ /* SD Card publishes its RCA. */
+ errorstate = SDMMC_CmdSetRelAdd(hsd->Instance, &sd_rca);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+ }
+ if(hsd->SdCard.CardType != CARD_SECURED)
+ {
+ /* Get the SD card RCA */
+ hsd->SdCard.RelCardAdd = sd_rca;
+
+ /* Send CMD9 SEND_CSD with argument as card's RCA */
+ errorstate = SDMMC_CmdSendCSD(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+ else
+ {
+ /* Get Card Specific Data */
+ hsd->CSD[0U] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+ hsd->CSD[1U] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP2);
+ hsd->CSD[2U] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP3);
+ hsd->CSD[3U] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP4);
+ }
+ }
+
+ /* Get the Card Class */
+ hsd->SdCard.Class = (SDMMC_GetResponse(hsd->Instance, SDMMC_RESP2) >> 20U);
+
+ /* Get CSD parameters */
+ if (HAL_SD_GetCardCSD(hsd, &CSD) != HAL_OK)
+ {
+ return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ }
+
+ /* Select the Card */
+ errorstate = SDMMC_CmdSelDesel(hsd->Instance, (uint32_t)(((uint32_t)hsd->SdCard.RelCardAdd) << 16U));
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* All cards are initialized */
+ return HAL_SD_ERROR_NONE;
+}
+
+/**
+ * @brief Enquires cards about their operating voltage and configures clock
+ * controls and stores SD information that will be needed in future
+ * in the SD handle.
+ * @param hsd: Pointer to SD handle
+ * @retval error state
+ */
+static uint32_t SD_PowerON(SD_HandleTypeDef *hsd)
+{
+ __IO uint32_t count = 0U;
+ uint32_t response = 0U, validvoltage = 0U;
+ uint32_t errorstate;
+#if (USE_SD_TRANSCEIVER != 0U)
+ uint32_t tickstart = HAL_GetTick();
+#endif /* USE_SD_TRANSCEIVER */
+
+ /* CMD0: GO_IDLE_STATE */
+ errorstate = SDMMC_CmdGoIdleState(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* CMD8: SEND_IF_COND: Command available only on V2.0 cards */
+ errorstate = SDMMC_CmdOperCond(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->SdCard.CardVersion = CARD_V1_X;
+ /* CMD0: GO_IDLE_STATE */
+ errorstate = SDMMC_CmdGoIdleState(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ }
+ else
+ {
+ hsd->SdCard.CardVersion = CARD_V2_X;
+ }
+
+ if( hsd->SdCard.CardVersion == CARD_V2_X)
+ {
+ /* SEND CMD55 APP_CMD with RCA as 0 */
+ errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ }
+ }
+ /* SD CARD */
+ /* Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */
+ while((count < SDMMC_MAX_VOLT_TRIAL) && (validvoltage == 0U))
+ {
+ /* SEND CMD55 APP_CMD with RCA as 0 */
+ errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Send CMD41 */
+ errorstate = SDMMC_CmdAppOperCommand(hsd->Instance, SDMMC_VOLTAGE_WINDOW_SD | SDMMC_HIGH_CAPACITY | SD_SWITCH_1_8V_CAPACITY);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
+ }
+
+ /* Get command response */
+ response = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+
+ /* Get operating voltage*/
+ validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
+
+ count++;
+ }
+
+ if(count >= SDMMC_MAX_VOLT_TRIAL)
+ {
+ return HAL_SD_ERROR_INVALID_VOLTRANGE;
+ }
+
+ if((response & SDMMC_HIGH_CAPACITY) == SDMMC_HIGH_CAPACITY) /* (response &= SD_HIGH_CAPACITY) */
+ {
+ hsd->SdCard.CardType = CARD_SDHC_SDXC;
+#if (USE_SD_TRANSCEIVER != 0U)
+ if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
+ {
+ if((response & SD_SWITCH_1_8V_CAPACITY) == SD_SWITCH_1_8V_CAPACITY)
+ {
+ hsd->SdCard.CardSpeed = CARD_ULTRA_HIGH_SPEED;
+
+ /* Start switching procedue */
+ hsd->Instance->POWER |= SDMMC_POWER_VSWITCHEN;
+
+ /* Send CMD11 to switch 1.8V mode */
+ errorstate = SDMMC_CmdVoltageSwitch(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Check to CKSTOP */
+ while(( hsd->Instance->STA & SDMMC_FLAG_CKSTOP) != SDMMC_FLAG_CKSTOP)
+ {
+ if((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
+ {
+ return HAL_SD_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear CKSTOP Flag */
+ hsd->Instance->ICR = SDMMC_FLAG_CKSTOP;
+
+ /* Check to BusyD0 */
+ if(( hsd->Instance->STA & SDMMC_FLAG_BUSYD0) != SDMMC_FLAG_BUSYD0)
+ {
+ /* Error when activate Voltage Switch in SDMMC Peripheral */
+ return SDMMC_ERROR_UNSUPPORTED_FEATURE;
+ }
+ else
+ {
+ /* Enable Transceiver Switch PIN */
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->DriveTransceiver_1_8V_Callback(SET);
+#else
+ HAL_SD_DriveTransceiver_1_8V_Callback(SET);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+
+ /* Switch ready */
+ hsd->Instance->POWER |= SDMMC_POWER_VSWITCH;
+
+ /* Check VSWEND Flag */
+ while(( hsd->Instance->STA & SDMMC_FLAG_VSWEND) != SDMMC_FLAG_VSWEND)
+ {
+ if((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
+ {
+ return HAL_SD_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear VSWEND Flag */
+ hsd->Instance->ICR = SDMMC_FLAG_VSWEND;
+
+ /* Check BusyD0 status */
+ if(( hsd->Instance->STA & SDMMC_FLAG_BUSYD0) == SDMMC_FLAG_BUSYD0)
+ {
+ /* Error when enabling 1.8V mode */
+ return HAL_SD_ERROR_INVALID_VOLTRANGE;
+ }
+ /* Switch to 1.8V OK */
+
+ /* Disable VSWITCH FLAG from SDMMC Peripheral */
+ hsd->Instance->POWER = 0x13U;
+
+ /* Clean Status flags */
+ hsd->Instance->ICR = 0xFFFFFFFFU;
+ }
+ }
+ }
+#endif /* USE_SD_TRANSCEIVER */
+ }
+
+ return HAL_SD_ERROR_NONE;
+}
+
+/**
+ * @brief Turns the SDMMC output signals off.
+ * @param hsd: Pointer to SD handle
+ * @retval None
+ */
+static void SD_PowerOFF(SD_HandleTypeDef *hsd)
+{
+ /* Set Power State to OFF */
+ (void)SDMMC_PowerState_OFF(hsd->Instance);
+}
+
+/**
+ * @brief Send Status info command.
+ * @param hsd: pointer to SD handle
+ * @param pSDstatus: Pointer to the buffer that will contain the SD card status
+ * SD Status register)
+ * @retval error state
+ */
+static uint32_t SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t count;
+ uint32_t *pData = pSDstatus;
+
+ /* Check SD response */
+ if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
+ {
+ return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
+ }
+
+ /* Set block size for card if it is not equal to current block size for card */
+ errorstate = SDMMC_CmdBlockLength(hsd->Instance, 64U);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_NONE;
+ return errorstate;
+ }
+
+ /* Send CMD55 */
+ errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_NONE;
+ return errorstate;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = 64U;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_64B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_ENABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+
+ /* Send ACMD13 (SD_APP_STAUS) with argument as card's RCA */
+ errorstate = SDMMC_CmdStatusRegister(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_NONE;
+ return errorstate;
+ }
+
+ /* Get status data */
+ while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
+ {
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
+ {
+ for(count = 0U; count < 8U; count++)
+ {
+ *pData = SDMMC_ReadFIFO(hsd->Instance);
+ pData++;
+ }
+ }
+
+ if((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
+ {
+ return HAL_SD_ERROR_TIMEOUT;
+ }
+ }
+
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ return HAL_SD_ERROR_DATA_TIMEOUT;
+ }
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ return HAL_SD_ERROR_DATA_CRC_FAIL;
+ }
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ return HAL_SD_ERROR_RX_OVERRUN;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ while ((__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DPSMACT)))
+ {
+ *pData = SDMMC_ReadFIFO(hsd->Instance);
+ pData++;
+
+ if((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
+ {
+ return HAL_SD_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear all the static status flags*/
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ return HAL_SD_ERROR_NONE;
+}
+
+/**
+ * @brief Returns the current card's status.
+ * @param hsd: Pointer to SD handle
+ * @param pCardStatus: pointer to the buffer that will contain the SD card
+ * status (Card Status register)
+ * @retval error state
+ */
+static uint32_t SD_SendStatus(SD_HandleTypeDef *hsd, uint32_t *pCardStatus)
+{
+ uint32_t errorstate;
+
+ if(pCardStatus == NULL)
+ {
+ return HAL_SD_ERROR_PARAM;
+ }
+
+ /* Send Status command */
+ errorstate = SDMMC_CmdSendStatus(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Get SD card status */
+ *pCardStatus = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+
+ return HAL_SD_ERROR_NONE;
+}
+
+/**
+ * @brief Enables the SDMMC wide bus mode.
+ * @param hsd: pointer to SD handle
+ * @retval error state
+ */
+static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd)
+{
+ uint32_t scr[2U] = {0UL, 0UL};
+ uint32_t errorstate;
+
+ if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
+ {
+ return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
+ }
+
+ /* Get SCR Register */
+ errorstate = SD_FindSCR(hsd, scr);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* If requested card supports wide bus operation */
+ if((scr[1U] & SDMMC_WIDE_BUS_SUPPORT) != SDMMC_ALLZERO)
+ {
+ /* Send CMD55 APP_CMD with argument as card's RCA.*/
+ errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
+ errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ return HAL_SD_ERROR_NONE;
+ }
+ else
+ {
+ return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
+ }
+}
+
+/**
+ * @brief Disables the SDMMC wide bus mode.
+ * @param hsd: Pointer to SD handle
+ * @retval error state
+ */
+static uint32_t SD_WideBus_Disable(SD_HandleTypeDef *hsd)
+{
+ uint32_t scr[2U] = {0UL, 0UL};
+ uint32_t errorstate;
+
+ if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
+ {
+ return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
+ }
+
+ /* Get SCR Register */
+ errorstate = SD_FindSCR(hsd, scr);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* If requested card supports 1 bit mode operation */
+ if((scr[1U] & SDMMC_SINGLE_BUS_SUPPORT) != SDMMC_ALLZERO)
+ {
+ /* Send CMD55 APP_CMD with argument as card's RCA */
+ errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Send ACMD6 APP_CMD with argument as 0 for single bus mode */
+ errorstate = SDMMC_CmdBusWidth(hsd->Instance, 0U);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ return HAL_SD_ERROR_NONE;
+ }
+ else
+ {
+ return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
+ }
+}
+
+
+/**
+ * @brief Finds the SD card SCR register value.
+ * @param hsd: Pointer to SD handle
+ * @param pSCR: pointer to the buffer that will contain the SCR value
+ * @retval error state
+ */
+static uint32_t SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t index = 0U;
+ uint32_t tempscr[2U] = {0UL, 0UL};
+ uint32_t *scr = pSCR;
+
+ /* Set Block Size To 8 Bytes */
+ errorstate = SDMMC_CmdBlockLength(hsd->Instance, 8U);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Send CMD55 APP_CMD with argument as card's RCA */
+ errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)((hsd->SdCard.RelCardAdd) << 16U));
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = 8U;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_8B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_ENABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+
+ /* Send ACMD51 SD_APP_SEND_SCR with argument as 0 */
+ errorstate = SDMMC_CmdSendSCR(hsd->Instance);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND | SDMMC_FLAG_DATAEND))
+ {
+ if((!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOE)) && (index == 0U))
+ {
+ tempscr[0] = SDMMC_ReadFIFO(hsd->Instance);
+ tempscr[1] = SDMMC_ReadFIFO(hsd->Instance);
+ index++;
+ }
+
+
+ if((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
+ {
+ return HAL_SD_ERROR_TIMEOUT;
+ }
+ }
+
+ if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ return HAL_SD_ERROR_DATA_TIMEOUT;
+ }
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ return HAL_SD_ERROR_DATA_CRC_FAIL;
+ }
+ else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
+
+ return HAL_SD_ERROR_RX_OVERRUN;
+ }
+ else
+ {
+ /* No error flag set */
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ *scr = (((tempscr[1] & SDMMC_0TO7BITS) << 24) | ((tempscr[1] & SDMMC_8TO15BITS) << 8) |\
+ ((tempscr[1] & SDMMC_16TO23BITS) >> 8) | ((tempscr[1] & SDMMC_24TO31BITS) >> 24));
+ scr++;
+ *scr = (((tempscr[0] & SDMMC_0TO7BITS) << 24) | ((tempscr[0] & SDMMC_8TO15BITS) << 8) |\
+ ((tempscr[0] & SDMMC_16TO23BITS) >> 8) | ((tempscr[0] & SDMMC_24TO31BITS) >> 24));
+
+ }
+
+ return HAL_SD_ERROR_NONE;
+}
+
+/**
+ * @brief Wrap up reading in non-blocking mode.
+ * @param hsd: pointer to a SD_HandleTypeDef structure that contains
+ * the configuration information.
+ * @retval None
+ */
+static void SD_Read_IT(SD_HandleTypeDef *hsd)
+{
+ uint32_t count, data;
+ uint8_t* tmp;
+
+ tmp = hsd->pRxBuffPtr;
+
+ if (hsd->RxXferSize >= 32U)
+ {
+ /* Read data from SDMMC Rx FIFO */
+ for(count = 0U; count < 8U; count++)
+ {
+ data = SDMMC_ReadFIFO(hsd->Instance);
+ *tmp = (uint8_t)(data & 0xFFU);
+ tmp++;
+ *tmp = (uint8_t)((data >> 8U) & 0xFFU);
+ tmp++;
+ *tmp = (uint8_t)((data >> 16U) & 0xFFU);
+ tmp++;
+ *tmp = (uint8_t)((data >> 24U) & 0xFFU);
+ tmp++;
+ }
+
+ hsd->pRxBuffPtr = tmp;
+ hsd->RxXferSize -= 32U;
+ }
+}
+
+/**
+ * @brief Wrap up writing in non-blocking mode.
+ * @param hsd: pointer to a SD_HandleTypeDef structure that contains
+ * the configuration information.
+ * @retval None
+ */
+static void SD_Write_IT(SD_HandleTypeDef *hsd)
+{
+ uint32_t count, data;
+ uint8_t* tmp;
+
+ tmp = hsd->pTxBuffPtr;
+
+ if (hsd->TxXferSize >= 32U)
+ {
+ /* Write data to SDMMC Tx FIFO */
+ for(count = 0U; count < 8U; count++)
+ {
+ data = (uint32_t)(*tmp);
+ tmp++;
+ data |= ((uint32_t)(*tmp) << 8U);
+ tmp++;
+ data |= ((uint32_t)(*tmp) << 16U);
+ tmp++;
+ data |= ((uint32_t)(*tmp) << 24U);
+ tmp++;
+ (void)SDMMC_WriteFIFO(hsd->Instance, &data);
+ }
+
+ hsd->pTxBuffPtr = tmp;
+ hsd->TxXferSize -= 32U;
+ }
+}
+
+/**
+ * @brief Switches the SD card to High Speed mode.
+ * This API must be used after "Transfer State"
+ * @note This operation should be followed by the configuration
+ * of PLL to have SDMMCCK clock between 50 and 120 MHz
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+uint32_t SD_HighSpeed(SD_HandleTypeDef *hsd)
+{
+ uint32_t errorstate = HAL_SD_ERROR_NONE;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+ uint32_t SD_hs[16] = {0};
+ uint32_t count, loop = 0 ;
+ uint32_t Timeout = HAL_GetTick();
+
+ if(hsd->SdCard.CardSpeed == CARD_NORMAL_SPEED)
+ {
+ /* Standard Speed Card <= 12.5Mhz */
+ return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
+ }
+
+ if(hsd->SdCard.CardSpeed == CARD_HIGH_SPEED)
+ {
+ /* Initialize the Data control register */
+ hsd->Instance->DCTRL = 0;
+ errorstate = SDMMC_CmdBlockLength(hsd->Instance, 64U);
+
+ if (errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ sdmmc_datainitstructure.DataTimeOut = SDMMC_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = 64U;
+ sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_64B ;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+
+ (void)SDMMC_ConfigData(hsd->Instance, &sdmmc_datainitstructure);
+
+
+ errorstate = SDMMC_CmdSwitch(hsd->Instance,SDMMC_SDR25_SWITCH_PATTERN);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND| SDMMC_FLAG_DATAEND ))
+ {
+ if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
+ {
+ for (count = 0U; count < 8U; count++)
+ {
+ SD_hs[(8U*loop)+count] = SDMMC_ReadFIFO(hsd->Instance);
+ }
+ loop ++;
+ }
+
+ if((HAL_GetTick()-Timeout) >= SDMMC_DATATIMEOUT)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
+ hsd->State= HAL_SD_STATE_READY;
+ return HAL_SD_ERROR_TIMEOUT;
+ }
+ }
+
+ if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ return errorstate;
+ }
+ else if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ errorstate = SDMMC_ERROR_DATA_CRC_FAIL;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
+
+ errorstate = SDMMC_ERROR_RX_OVERRUN;
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ /* Test if the switch mode HS is ok */
+ if ((((uint8_t*)SD_hs)[13] & 2U) != 2U)
+ {
+ errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
+ }
+
+ }
+
+ return errorstate;
+}
+
+#if (USE_SD_TRANSCEIVER != 0U)
+/**
+ * @brief Switches the SD card to Ultra High Speed mode.
+ * This API must be used after "Transfer State"
+ * @note This operation should be followed by the configuration
+ * of PLL to have SDMMCCK clock between 50 and 120 MHz
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static uint32_t SD_UltraHighSpeed(SD_HandleTypeDef *hsd)
+{
+ uint32_t errorstate = HAL_SD_ERROR_NONE;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+ uint32_t SD_hs[16] = {0};
+ uint32_t count, loop = 0 ;
+ uint32_t Timeout = HAL_GetTick();
+
+ if(hsd->SdCard.CardSpeed == CARD_NORMAL_SPEED)
+ {
+ /* Standard Speed Card <= 12.5Mhz */
+ return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
+ }
+
+ if(hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)
+ {
+ /* Initialize the Data control register */
+ hsd->Instance->DCTRL = 0;
+ errorstate = SDMMC_CmdBlockLength(hsd->Instance, 64U);
+
+ if (errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ sdmmc_datainitstructure.DataTimeOut = SDMMC_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = 64U;
+ sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_64B ;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+
+ if ( SDMMC_ConfigData(hsd->Instance, &sdmmc_datainitstructure) != HAL_OK)
+ {
+ return (HAL_SD_ERROR_GENERAL_UNKNOWN_ERR);
+ }
+
+ errorstate = SDMMC_CmdSwitch(hsd->Instance, SDMMC_SDR104_SWITCH_PATTERN);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND| SDMMC_FLAG_DATAEND ))
+ {
+ if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
+ {
+ for (count = 0U; count < 8U; count++)
+ {
+ SD_hs[(8U*loop)+count] = SDMMC_ReadFIFO(hsd->Instance);
+ }
+ loop ++;
+ }
+
+ if((HAL_GetTick()-Timeout) >= SDMMC_DATATIMEOUT)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
+ hsd->State= HAL_SD_STATE_READY;
+ return HAL_SD_ERROR_TIMEOUT;
+ }
+ }
+
+ if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ return errorstate;
+ }
+ else if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ errorstate = SDMMC_ERROR_DATA_CRC_FAIL;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
+
+ errorstate = SDMMC_ERROR_RX_OVERRUN;
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ /* Test if the switch mode HS is ok */
+ if ((((uint8_t*)SD_hs)[13] & 2U) != 2U)
+ {
+ errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
+ }
+ else
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->DriveTransceiver_1_8V_Callback(SET);
+#else
+ HAL_SD_DriveTransceiver_1_8V_Callback(SET);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+#if defined (DLYB_SDMMC1) || defined (DLYB_SDMMC2)
+ /* Enable DelayBlock Peripheral */
+ /* SDMMC_FB_CLK tuned feedback clock selected as receive clock, for SDR104 */
+ MODIFY_REG(hsd->Instance->CLKCR, SDMMC_CLKCR_SELCLKRX,SDMMC_CLKCR_SELCLKRX_1);
+ if (DelayBlock_Enable(SD_GET_DLYB_INSTANCE(hsd->Instance)) != HAL_OK)
+ {
+ return (HAL_SD_ERROR_GENERAL_UNKNOWN_ERR);
+ }
+#endif /* (DLYB_SDMMC1) || (DLYB_SDMMC2) */
+ }
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Switches the SD card to Double Data Rate (DDR) mode.
+ * This API must be used after "Transfer State"
+ * @note This operation should be followed by the configuration
+ * of PLL to have SDMMCCK clock less than 50MHz
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static uint32_t SD_DDR_Mode(SD_HandleTypeDef *hsd)
+{
+ uint32_t errorstate = HAL_SD_ERROR_NONE;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+ uint32_t SD_hs[16] = {0};
+ uint32_t count, loop = 0 ;
+ uint32_t Timeout = HAL_GetTick();
+
+ if(hsd->SdCard.CardSpeed == CARD_NORMAL_SPEED)
+ {
+ /* Standard Speed Card <= 12.5Mhz */
+ return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
+ }
+
+ if(hsd->SdCard.CardSpeed == CARD_ULTRA_HIGH_SPEED)
+ {
+ /* Initialize the Data control register */
+ hsd->Instance->DCTRL = 0;
+ errorstate = SDMMC_CmdBlockLength(hsd->Instance, 64U);
+
+ if (errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ sdmmc_datainitstructure.DataTimeOut = SDMMC_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = 64U;
+ sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_64B ;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+
+ if ( SDMMC_ConfigData(hsd->Instance, &sdmmc_datainitstructure) != HAL_OK)
+ {
+ return (HAL_SD_ERROR_GENERAL_UNKNOWN_ERR);
+ }
+
+ errorstate = SDMMC_CmdSwitch(hsd->Instance, SDMMC_DDR50_SWITCH_PATTERN);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ return errorstate;
+ }
+
+ while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND| SDMMC_FLAG_DATAEND ))
+ {
+ if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
+ {
+ for (count = 0U; count < 8U; count++)
+ {
+ SD_hs[(8U*loop)+count] = SDMMC_ReadFIFO(hsd->Instance);
+ }
+ loop ++;
+ }
+
+ if((HAL_GetTick()-Timeout) >= SDMMC_DATATIMEOUT)
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_TIMEOUT;
+ hsd->State= HAL_SD_STATE_READY;
+ return HAL_SD_ERROR_TIMEOUT;
+ }
+ }
+
+ if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ return errorstate;
+ }
+ else if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ errorstate = SDMMC_ERROR_DATA_CRC_FAIL;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
+
+ errorstate = SDMMC_ERROR_RX_OVERRUN;
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ /* Test if the switch mode is ok */
+ if ((((uint8_t*)SD_hs)[13] & 2U) != 2U)
+ {
+ errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
+ }
+ else
+ {
+#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
+ hsd->DriveTransceiver_1_8V_Callback(SET);
+#else
+ HAL_SD_DriveTransceiver_1_8V_Callback(SET);
+#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
+#if defined (DLYB_SDMMC1) || defined (DLYB_SDMMC2)
+ /* Enable DelayBlock Peripheral */
+ /* SDMMC_CKin feedback clock selected as receive clock, for DDR50 */
+ MODIFY_REG(hsd->Instance->CLKCR, SDMMC_CLKCR_SELCLKRX,SDMMC_CLKCR_SELCLKRX_0);
+ if (DelayBlock_Enable(SD_GET_DLYB_INSTANCE(hsd->Instance)) != HAL_OK)
+ {
+ return (HAL_SD_ERROR_GENERAL_UNKNOWN_ERR);
+ }
+#endif /* (DLYB_SDMMC1) || (DLYB_SDMMC2) */
+ }
+ }
+
+ return errorstate;
+}
+
+#endif /* USE_SD_TRANSCEIVER */
+
+/**
+ * @brief Read DMA Buffer 0 Transfer completed callbacks
+ * @param hsd: SD handle
+ * @retval None
+ */
+__weak void HAL_SDEx_Read_DMADoubleBuf0CpltCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SDEx_Read_DMADoubleBuf0CpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Read DMA Buffer 1 Transfer completed callbacks
+ * @param hsd: SD handle
+ * @retval None
+ */
+__weak void HAL_SDEx_Read_DMADoubleBuf1CpltCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SDEx_Read_DMADoubleBuf1CpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Write DMA Buffer 0 Transfer completed callbacks
+ * @param hsd: SD handle
+ * @retval None
+ */
+__weak void HAL_SDEx_Write_DMADoubleBuf0CpltCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SDEx_Write_DMADoubleBuf0CpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Write DMA Buffer 1 Transfer completed callbacks
+ * @param hsd: SD handle
+ * @retval None
+ */
+__weak void HAL_SDEx_Write_DMADoubleBuf1CpltCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SDEx_Write_DMADoubleBuf1CpltCallback can be implemented in the user file
+ */
+}
+
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SD_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_sd_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sd_ex.c
new file mode 100644
index 0000000000..674619d98b
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sd_ex.c
@@ -0,0 +1,305 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_sd_ex.c
+ * @author MCD Application Team
+ * @brief SD card Extended HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Secure Digital (SD) peripheral:
+ * + Extended features functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The SD Extension HAL driver can be used as follows:
+ (+) Configure Buffer0 and Buffer1 start address and Buffer size using HAL_SDEx_ConfigDMAMultiBuffer() function.
+ (+) Start Read and Write for multibuffer mode using HAL_SDEx_ReadBlocksDMAMultiBuffer() and HAL_SDEx_WriteBlocksDMAMultiBuffer() functions.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SDEx SDEx
+ * @brief SD Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_SD_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup SDEx_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup SDEx_Exported_Functions_Group1
+ * @brief Multibuffer functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Multibuffer functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to configure the multibuffer mode and start read and write
+ multibuffer mode for SD HAL driver.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure DMA Dual Buffer mode. The Data transfer is managed by an Internal DMA.
+ * @param hsd: SD handle
+ * @param pDataBuffer0: Pointer to the buffer0 that will contain/receive the transfered data
+ * @param pDataBuffer1: Pointer to the buffer1 that will contain/receive the transfered data
+ * @param BufferSize: Size of Buffer0 in Blocks. Buffer0 and Buffer1 must have the same size.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDEx_ConfigDMAMultiBuffer(SD_HandleTypeDef *hsd, uint32_t *pDataBuffer0, uint32_t *pDataBuffer1, uint32_t BufferSize)
+{
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ hsd->Instance->IDMABASE0= (uint32_t) pDataBuffer0;
+ hsd->Instance->IDMABASE1= (uint32_t) pDataBuffer1;
+ hsd->Instance->IDMABSIZE= (uint32_t) (BLOCKSIZE * BufferSize);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The received Data will be stored in Buffer0 and Buffer1.
+ * Buffer0, Buffer1 and BufferSize need to be configured by function HAL_SDEx_ConfigDMAMultiBuffer before call this function.
+ * @param hsd: SD handle
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Total number of blocks to read
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDEx_ReadBlocksDMAMultiBuffer(SD_HandleTypeDef *hsd, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t DmaBase0_reg, DmaBase1_reg;
+ uint32_t add = BlockAdd;
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ DmaBase0_reg = hsd->Instance->IDMABASE0;
+ DmaBase1_reg = hsd->Instance->IDMABASE1;
+ if ((hsd->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0;
+ /* Clear old Flags*/
+ __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
+
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+
+ hsd->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
+
+ __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
+
+ hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
+
+ /* Read Blocks in DMA mode */
+ hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
+
+ /* Read Multi Block command */
+ errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->ErrorCode |= errorstate;
+ return HAL_ERROR;
+ }
+
+ __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | SDMMC_IT_IDMABTC));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+}
+
+/**
+ * @brief Write block(s) to a specified address in a card. The transfered Data are stored in Buffer0 and Buffer1.
+ * Buffer0, Buffer1 and BufferSize need to be configured by function HAL_SDEx_ConfigDMAMultiBuffer before call this function.
+ * @param hsd: SD handle
+ * @param BlockAdd: Block Address from where data is to be read
+ * @param NumberOfBlocks: Total number of blocks to read
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_SDEx_WriteBlocksDMAMultiBuffer(SD_HandleTypeDef *hsd, uint32_t BlockAdd, uint32_t NumberOfBlocks)
+{
+ SDMMC_DataInitTypeDef config;
+ uint32_t errorstate;
+ uint32_t DmaBase0_reg, DmaBase1_reg;
+ uint32_t add = BlockAdd;
+
+ if(hsd->State == HAL_SD_STATE_READY)
+ {
+ if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
+ {
+ hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ DmaBase0_reg = hsd->Instance->IDMABASE0;
+ DmaBase1_reg = hsd->Instance->IDMABASE1;
+ if ((hsd->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
+ {
+ hsd->ErrorCode = HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
+ return HAL_ERROR;
+ }
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0;
+
+ hsd->ErrorCode = HAL_SD_ERROR_NONE;
+
+ hsd->State = HAL_SD_STATE_BUSY;
+
+ if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
+ {
+ add *= 512U;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ config.DataTimeOut = SDMMC_DATATIMEOUT;
+ config.DataLength = BLOCKSIZE * NumberOfBlocks;
+ config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ config.DPSM = SDMMC_DPSM_DISABLE;
+ (void)SDMMC_ConfigData(hsd->Instance, &config);
+
+ __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
+
+ hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
+
+ /* Write Blocks in DMA mode */
+ hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
+
+ /* Write Multi Block command */
+ errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
+ if(errorstate != HAL_SD_ERROR_NONE)
+ {
+ hsd->State = HAL_SD_STATE_READY;
+ hsd->ErrorCode |= errorstate;
+ return HAL_ERROR;
+ }
+
+ __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_IT_IDMABTC));
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+/**
+ * @brief Change the DMA Buffer0 or Buffer1 address on the fly.
+ * @param hsd: pointer to a SD_HandleTypeDef structure.
+ * @param Buffer: the buffer to be changed, This parameter can be one of
+ * the following values: SD_DMA_BUFFER0 or SD_DMA_BUFFER1
+ * @param pDataBuffer: The new address
+ * @note The BUFFER0 address can be changed only when the current transfer use
+ * BUFFER1 and the BUFFER1 address can be changed only when the current
+ * transfer use BUFFER0.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDEx_ChangeDMABuffer(SD_HandleTypeDef *hsd, HAL_SDEx_DMABuffer_MemoryTypeDef Buffer, uint32_t *pDataBuffer)
+{
+ if(Buffer == SD_DMA_BUFFER0)
+ {
+ /* change the buffer0 address */
+ hsd->Instance->IDMABASE0 = (uint32_t)pDataBuffer;
+ }
+ else
+ {
+ /* change the memory1 address */
+ hsd->Instance->IDMABASE1 = (uint32_t)pDataBuffer;
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SD_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_sdram.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sdram.c
new file mode 100644
index 0000000000..3b0efe590a
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sdram.c
@@ -0,0 +1,1312 @@
+/**
+ ******************************************************************************
+ * @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.
+ *
+ @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 @ref 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 @ref HAL_SDRAM_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) 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 @ref HAL_SDRAM_Init and if the state is HAL_SDRAM_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_SDRAM_Init
+ and @ref HAL_SDRAM_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_SDRAM_Init and @ref 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 @ref HAL_SDRAM_RegisterCallback before calling @ref HAL_SDRAM_DeInit
+ or @ref 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 (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_SDRAM_MODULE_ENABLED
+
+/** @defgroup SDRAM SDRAM
+ * @brief SDRAM driver modules
+ * @{
+ */
+
+/**
+ @cond 0
+ */
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void SDRAM_DMACplt (MDMA_HandleTypeDef *hmdma);
+static void SDRAM_DMACpltProt(MDMA_HandleTypeDef *hmdma);
+static void SDRAM_DMAError (MDMA_HandleTypeDef *hmdma);
+/**
+ @endcond
+ */
+
+/* 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
+ }
+
+ /* 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
+
+ /* 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
+
+ /* 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)
+ {
+ 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;
+
+ /* 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
+ {
+ return 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)
+ {
+ 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;
+
+ /* 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
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+}
+
+#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User SDRAM Callback
+ * To be used instead of the weak (surcharged) 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;
+ }
+
+ /* 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_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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsdram);
+ return status;
+}
+
+/**
+ * @brief Unregister a User SDRAM Callback
+ * SDRAM Callback is redirected to the weak (surcharged) 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;
+
+ /* 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_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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsdram);
+ return status;
+}
+
+/**
+ * @brief Register a User SDRAM Callback for DMA transfers
+ * To be used instead of the weak (surcharged) 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
+
+/**
+ * @}
+ */
+
+/** @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(SDRAM_HandleTypeDef *hsdram)
+{
+ return hsdram->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ @cond 0
+ */
+/**
+ * @brief MDMA SDRAM process complete callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SDRAM_DMACplt(MDMA_HandleTypeDef *hmdma)
+{
+ 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
+}
+
+/**
+ * @brief MDMA SRAM process complete callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SDRAM_DMACpltProt(MDMA_HandleTypeDef *hmdma)
+{
+ 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
+}
+
+/**
+ * @brief MDMA SDRAM error callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SDRAM_DMAError(MDMA_HandleTypeDef *hmdma)
+{
+ 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
+}
+/**
+ @endcond
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SDRAM_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_smartcard.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_smartcard.c
new file mode 100644
index 0000000000..01237b07ca
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_smartcard.c
@@ -0,0 +1,3136 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_smartcard.c
+ * @author MCD Application Team
+ * @brief SMARTCARD HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the SMARTCARD peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Error functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The SMARTCARD HAL driver can be used as follows:
+
+ (#) Declare a SMARTCARD_HandleTypeDef handle structure (eg. SMARTCARD_HandleTypeDef hsmartcard).
+ (#) Associate a USART to the SMARTCARD handle hsmartcard.
+ (#) Initialize the SMARTCARD low level resources by implementing the HAL_SMARTCARD_MspInit() API:
+ (++) Enable the USARTx interface clock.
+ (++) USART pins configuration:
+ (+++) Enable the clock for the USART GPIOs.
+ (+++) Configure the USART pins (TX as alternate function pull-up, RX as alternate function Input).
+ (++) NVIC configuration if you need to use interrupt process (HAL_SMARTCARD_Transmit_IT()
+ and HAL_SMARTCARD_Receive_IT() APIs):
+ (+++) Configure the USARTx interrupt priority.
+ (+++) Enable the NVIC USART IRQ handle.
+ (++) DMA Configuration if you need to use DMA process (HAL_SMARTCARD_Transmit_DMA()
+ and HAL_SMARTCARD_Receive_DMA() APIs):
+ (+++) Declare a DMA handle structure for the Tx/Rx channel.
+ (+++) Enable the DMAx interface clock.
+ (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
+ (+++) Configure the DMA Tx/Rx channel.
+ (+++) Associate the initialized DMA handle to the SMARTCARD DMA Tx/Rx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
+
+ (#) Program the Baud Rate, Parity, Mode(Receiver/Transmitter), clock enabling/disabling and accordingly,
+ the clock parameters (parity, phase, last bit), prescaler value, guard time and NACK on transmission
+ error enabling or disabling in the hsmartcard handle Init structure.
+
+ (#) If required, program SMARTCARD advanced features (TX/RX pins swap, TimeOut, auto-retry counter,...)
+ in the hsmartcard handle AdvancedInit structure.
+
+ (#) Initialize the SMARTCARD registers by calling the HAL_SMARTCARD_Init() API:
+ (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
+ by calling the customized HAL_SMARTCARD_MspInit() API.
+ [..]
+ (@) The specific SMARTCARD interrupts (Transmission complete interrupt,
+ RXNE interrupt and Error Interrupts) will be managed using the macros
+ __HAL_SMARTCARD_ENABLE_IT() and __HAL_SMARTCARD_DISABLE_IT() inside the transmit and receive process.
+
+ [..]
+ [..] Three operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Send an amount of data in blocking mode using HAL_SMARTCARD_Transmit()
+ (+) Receive an amount of data in blocking mode using HAL_SMARTCARD_Receive()
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Send an amount of data in non-blocking mode using HAL_SMARTCARD_Transmit_IT()
+ (+) At transmission end of transfer HAL_SMARTCARD_TxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SMARTCARD_TxCpltCallback()
+ (+) Receive an amount of data in non-blocking mode using HAL_SMARTCARD_Receive_IT()
+ (+) At reception end of transfer HAL_SMARTCARD_RxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SMARTCARD_RxCpltCallback()
+ (+) In case of transfer Error, HAL_SMARTCARD_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_SMARTCARD_ErrorCallback()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Send an amount of data in non-blocking mode (DMA) using HAL_SMARTCARD_Transmit_DMA()
+ (+) At transmission end of transfer HAL_SMARTCARD_TxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SMARTCARD_TxCpltCallback()
+ (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SMARTCARD_Receive_DMA()
+ (+) At reception end of transfer HAL_SMARTCARD_RxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SMARTCARD_RxCpltCallback()
+ (+) In case of transfer Error, HAL_SMARTCARD_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_SMARTCARD_ErrorCallback()
+
+ *** SMARTCARD HAL driver macros list ***
+ ========================================
+ [..]
+ Below the list of most used macros in SMARTCARD HAL driver.
+
+ (+) __HAL_SMARTCARD_GET_FLAG : Check whether or not the specified SMARTCARD flag is set
+ (+) __HAL_SMARTCARD_CLEAR_FLAG : Clear the specified SMARTCARD pending flag
+ (+) __HAL_SMARTCARD_ENABLE_IT: Enable the specified SMARTCARD interrupt
+ (+) __HAL_SMARTCARD_DISABLE_IT: Disable the specified SMARTCARD interrupt
+ (+) __HAL_SMARTCARD_GET_IT_SOURCE: Check whether or not the specified SMARTCARD interrupt is enabled
+
+ [..]
+ (@) You can refer to the SMARTCARD HAL driver header file for more useful macros
+
+ ##### Callback registration #####
+ ==================================
+
+ [..]
+ The compilation define USE_HAL_SMARTCARD_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ [..]
+ Use Function @ref HAL_SMARTCARD_RegisterCallback() to register a user callback.
+ Function @ref HAL_SMARTCARD_RegisterCallback() allows to register following callbacks:
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) AbortCpltCallback : Abort Complete Callback.
+ (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
+ (+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
+ (+) RxFifoFullCallback : Rx Fifo Full Callback.
+ (+) TxFifoEmptyCallback : Tx Fifo Empty Callback.
+ (+) MspInitCallback : SMARTCARD MspInit.
+ (+) MspDeInitCallback : SMARTCARD MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function @ref HAL_SMARTCARD_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function.
+ @ref HAL_SMARTCARD_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) AbortCpltCallback : Abort Complete Callback.
+ (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
+ (+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
+ (+) RxFifoFullCallback : Rx Fifo Full Callback.
+ (+) TxFifoEmptyCallback : Tx Fifo Empty Callback.
+ (+) MspInitCallback : SMARTCARD MspInit.
+ (+) MspDeInitCallback : SMARTCARD MspDeInit.
+
+ [..]
+ By default, after the @ref HAL_SMARTCARD_Init() and when the state is HAL_SMARTCARD_STATE_RESET
+ all callbacks are set to the corresponding weak (surcharged) functions:
+ examples @ref HAL_SMARTCARD_TxCpltCallback(), @ref HAL_SMARTCARD_RxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_SMARTCARD_Init()
+ and @ref HAL_SMARTCARD_DeInit() only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_SMARTCARD_Init() and @ref HAL_SMARTCARD_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
+
+ [..]
+ Callbacks can be registered/unregistered in HAL_SMARTCARD_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_SMARTCARD_STATE_READY or HAL_SMARTCARD_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 @ref HAL_SMARTCARD_RegisterCallback() before calling @ref HAL_SMARTCARD_DeInit()
+ or @ref HAL_SMARTCARD_Init() function.
+
+ [..]
+ When The compilation define USE_HAL_SMARTCARD_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available
+ and weak (surcharged) callbacks are used.
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SMARTCARD SMARTCARD
+ * @brief HAL SMARTCARD module driver
+ * @{
+ */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup SMARTCARD_Private_Constants SMARTCARD Private Constants
+ * @{
+ */
+#define SMARTCARD_TEACK_REACK_TIMEOUT 1000U /*!< SMARTCARD TX or RX enable acknowledge time-out value */
+
+#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \
+ USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8| \
+ USART_CR1_FIFOEN )) /*!< USART CR1 fields of parameters set by SMARTCARD_SetConfig API */
+
+#define USART_CR2_CLK_FIELDS ((uint32_t)(USART_CR2_CLKEN | USART_CR2_CPOL | USART_CR2_CPHA | \
+ USART_CR2_LBCL)) /*!< SMARTCARD clock-related USART CR2 fields of parameters */
+
+#define USART_CR2_FIELDS ((uint32_t)(USART_CR2_RTOEN | USART_CR2_CLK_FIELDS | USART_CR2_STOP)) /*!< USART CR2 fields of parameters set by SMARTCARD_SetConfig API */
+
+#define USART_CR3_FIELDS ((uint32_t)(USART_CR3_ONEBIT | USART_CR3_NACK | USART_CR3_SCARCNT | \
+ USART_CR3_TXFTCFG | USART_CR3_RXFTCFG )) /*!< USART CR3 fields of parameters set by SMARTCARD_SetConfig API */
+
+#define USART_BRR_MIN 0x10U /*!< USART BRR minimum authorized value */
+
+#define USART_BRR_MAX 0x0000FFFFU /*!< USART BRR maximum authorized value */
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup SMARTCARD_Private_Functions
+ * @{
+ */
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+void SMARTCARD_InitCallbacksToDefault(SMARTCARD_HandleTypeDef *hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
+static HAL_StatusTypeDef SMARTCARD_SetConfig(SMARTCARD_HandleTypeDef *hsmartcard);
+static void SMARTCARD_AdvFeatureConfig(SMARTCARD_HandleTypeDef *hsmartcard);
+static HAL_StatusTypeDef SMARTCARD_CheckIdleState(SMARTCARD_HandleTypeDef *hsmartcard);
+static HAL_StatusTypeDef SMARTCARD_WaitOnFlagUntilTimeout(SMARTCARD_HandleTypeDef *hsmartcard, uint32_t Flag,
+ FlagStatus Status, uint32_t Tickstart, uint32_t Timeout);
+static void SMARTCARD_EndTxTransfer(SMARTCARD_HandleTypeDef *hsmartcard);
+static void SMARTCARD_EndRxTransfer(SMARTCARD_HandleTypeDef *hsmartcard);
+static void SMARTCARD_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void SMARTCARD_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SMARTCARD_DMAError(DMA_HandleTypeDef *hdma);
+static void SMARTCARD_DMAAbortOnError(DMA_HandleTypeDef *hdma);
+static void SMARTCARD_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
+static void SMARTCARD_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
+static void SMARTCARD_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
+static void SMARTCARD_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
+static void SMARTCARD_TxISR(SMARTCARD_HandleTypeDef *hsmartcard);
+static void SMARTCARD_TxISR_FIFOEN(SMARTCARD_HandleTypeDef *hsmartcard);
+static void SMARTCARD_EndTransmit_IT(SMARTCARD_HandleTypeDef *hsmartcard);
+static void SMARTCARD_RxISR(SMARTCARD_HandleTypeDef *hsmartcard);
+static void SMARTCARD_RxISR_FIFOEN(SMARTCARD_HandleTypeDef *hsmartcard);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup SMARTCARD_Exported_Functions SMARTCARD Exported Functions
+ * @{
+ */
+
+/** @defgroup SMARTCARD_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and Configuration functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to initialize the USARTx
+ associated to the SmartCard.
+ (+) These parameters can be configured:
+ (++) Baud Rate
+ (++) Parity: parity should be enabled, frame Length is fixed to 8 bits plus parity
+ (++) Receiver/transmitter modes
+ (++) Synchronous mode (and if enabled, phase, polarity and last bit parameters)
+ (++) Prescaler value
+ (++) Guard bit time
+ (++) NACK enabling or disabling on transmission error
+
+ (+) The following advanced features can be configured as well:
+ (++) TX and/or RX pin level inversion
+ (++) data logical level inversion
+ (++) RX and TX pins swap
+ (++) RX overrun detection disabling
+ (++) DMA disabling on RX error
+ (++) MSB first on communication line
+ (++) Time out enabling (and if activated, timeout value)
+ (++) Block length
+ (++) Auto-retry counter
+ [..]
+ The HAL_SMARTCARD_Init() API follows the USART synchronous configuration procedures
+ (details for the procedures are available in reference manual).
+
+@endverbatim
+
+ The USART frame format is given in the following table:
+
+ Table 1. USART frame format.
+ +---------------------------------------------------------------+
+ | M1M0 bits | PCE bit | USART frame |
+ |-----------------------|---------------------------------------|
+ | 01 | 1 | | SB | 8 bit data | PB | STB | |
+ +---------------------------------------------------------------+
+
+
+ * @{
+ */
+
+/**
+ * @brief Initialize the SMARTCARD mode according to the specified
+ * parameters in the SMARTCARD_HandleTypeDef and initialize the associated handle.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_Init(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Check the SMARTCARD handle allocation */
+ if (hsmartcard == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the USART associated to the SMARTCARD handle */
+ assert_param(IS_SMARTCARD_INSTANCE(hsmartcard->Instance));
+
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hsmartcard->Lock = HAL_UNLOCKED;
+
+#if USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1
+ SMARTCARD_InitCallbacksToDefault(hsmartcard);
+
+ if (hsmartcard->MspInitCallback == NULL)
+ {
+ hsmartcard->MspInitCallback = HAL_SMARTCARD_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hsmartcard->MspInitCallback(hsmartcard);
+#else
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_SMARTCARD_MspInit(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
+ }
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY;
+
+ /* Disable the Peripheral to set smartcard mode */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+
+ /* In SmartCard mode, the following bits must be kept cleared:
+ - LINEN in the USART_CR2 register,
+ - HDSEL and IREN bits in the USART_CR3 register.*/
+ CLEAR_BIT(hsmartcard->Instance->CR2, USART_CR2_LINEN);
+ CLEAR_BIT(hsmartcard->Instance->CR3, (USART_CR3_HDSEL | USART_CR3_IREN));
+
+ /* set the USART in SMARTCARD mode */
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_SCEN);
+
+ /* Set the SMARTCARD Communication parameters */
+ if (SMARTCARD_SetConfig(hsmartcard) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the SMARTCARD transmission completion indication */
+ SMARTCARD_TRANSMISSION_COMPLETION_SETTING(hsmartcard);
+
+ if (hsmartcard->AdvancedInit.AdvFeatureInit != SMARTCARD_ADVFEATURE_NO_INIT)
+ {
+ SMARTCARD_AdvFeatureConfig(hsmartcard);
+ }
+
+ /* Enable the Peripheral */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+
+ /* TEACK and/or REACK to check before moving hsmartcard->gState and hsmartcard->RxState to Ready */
+ return (SMARTCARD_CheckIdleState(hsmartcard));
+}
+
+/**
+ * @brief DeInitialize the SMARTCARD peripheral.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_DeInit(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Check the SMARTCARD handle allocation */
+ if (hsmartcard == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the USART/UART associated to the SMARTCARD handle */
+ assert_param(IS_SMARTCARD_INSTANCE(hsmartcard->Instance));
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+
+ WRITE_REG(hsmartcard->Instance->CR1, 0x0U);
+ WRITE_REG(hsmartcard->Instance->CR2, 0x0U);
+ WRITE_REG(hsmartcard->Instance->CR3, 0x0U);
+ WRITE_REG(hsmartcard->Instance->RTOR, 0x0U);
+ WRITE_REG(hsmartcard->Instance->GTPR, 0x0U);
+
+ /* DeInit the low level hardware */
+#if USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1
+ if (hsmartcard->MspDeInitCallback == NULL)
+ {
+ hsmartcard->MspDeInitCallback = HAL_SMARTCARD_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ hsmartcard->MspDeInitCallback(hsmartcard);
+#else
+ HAL_SMARTCARD_MspDeInit(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
+
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+ hsmartcard->gState = HAL_SMARTCARD_STATE_RESET;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_RESET;
+
+ /* Process Unlock */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the SMARTCARD MSP.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARD_MspInit(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARD_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the SMARTCARD MSP.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARD_MspDeInit(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARD_MspDeInit can be implemented in the user file
+ */
+}
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User SMARTCARD Callback
+ * To be used instead of the weak predefined callback
+ * @param hsmartcard smartcard handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SMARTCARD_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_SMARTCARD_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_RX_FIFO_FULL_CB_ID Rx Fifo Full Callback ID
+ * @arg @ref HAL_SMARTCARD_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty Callback ID
+ * @arg @ref HAL_SMARTCARD_MSPINIT_CB_ID MspInit Callback ID
+ * @arg @ref HAL_SMARTCARD_MSPDEINIT_CB_ID MspDeInit Callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_RegisterCallback(SMARTCARD_HandleTypeDef *hsmartcard,
+ HAL_SMARTCARD_CallbackIDTypeDef CallbackID, pSMARTCARD_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hsmartcard);
+
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+
+ case HAL_SMARTCARD_TX_COMPLETE_CB_ID :
+ hsmartcard->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_RX_COMPLETE_CB_ID :
+ hsmartcard->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_ERROR_CB_ID :
+ hsmartcard->ErrorCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_ABORT_COMPLETE_CB_ID :
+ hsmartcard->AbortCpltCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID :
+ hsmartcard->AbortTransmitCpltCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID :
+ hsmartcard->AbortReceiveCpltCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_RX_FIFO_FULL_CB_ID :
+ hsmartcard->RxFifoFullCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_TX_FIFO_EMPTY_CB_ID :
+ hsmartcard->TxFifoEmptyCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_MSPINIT_CB_ID :
+ hsmartcard->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_MSPDEINIT_CB_ID :
+ hsmartcard->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hsmartcard->gState == HAL_SMARTCARD_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SMARTCARD_MSPINIT_CB_ID :
+ hsmartcard->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SMARTCARD_MSPDEINIT_CB_ID :
+ hsmartcard->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsmartcard);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an SMARTCARD callback
+ * SMARTCARD callback is redirected to the weak predefined callback
+ * @param hsmartcard smartcard handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SMARTCARD_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_SMARTCARD_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
+ * @arg @ref HAL_SMARTCARD_RX_FIFO_FULL_CB_ID Rx Fifo Full Callback ID
+ * @arg @ref HAL_SMARTCARD_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty Callback ID
+ * @arg @ref HAL_SMARTCARD_MSPINIT_CB_ID MspInit Callback ID
+ * @arg @ref HAL_SMARTCARD_MSPDEINIT_CB_ID MspDeInit Callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_UnRegisterCallback(SMARTCARD_HandleTypeDef *hsmartcard,
+ HAL_SMARTCARD_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hsmartcard);
+
+ if (HAL_SMARTCARD_STATE_READY == hsmartcard->gState)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SMARTCARD_TX_COMPLETE_CB_ID :
+ hsmartcard->TxCpltCallback = HAL_SMARTCARD_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ break;
+
+ case HAL_SMARTCARD_RX_COMPLETE_CB_ID :
+ hsmartcard->RxCpltCallback = HAL_SMARTCARD_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ break;
+
+ case HAL_SMARTCARD_ERROR_CB_ID :
+ hsmartcard->ErrorCallback = HAL_SMARTCARD_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_SMARTCARD_ABORT_COMPLETE_CB_ID :
+ hsmartcard->AbortCpltCallback = HAL_SMARTCARD_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ break;
+
+ case HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID :
+ hsmartcard->AbortTransmitCpltCallback = HAL_SMARTCARD_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
+ break;
+
+ case HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID :
+ hsmartcard->AbortReceiveCpltCallback = HAL_SMARTCARD_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
+ break;
+
+ case HAL_SMARTCARD_RX_FIFO_FULL_CB_ID :
+ hsmartcard->RxFifoFullCallback = HAL_SMARTCARDEx_RxFifoFullCallback; /* Legacy weak RxFifoFullCallback */
+ break;
+
+ case HAL_SMARTCARD_TX_FIFO_EMPTY_CB_ID :
+ hsmartcard->TxFifoEmptyCallback = HAL_SMARTCARDEx_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */
+ break;
+
+ case HAL_SMARTCARD_MSPINIT_CB_ID :
+ hsmartcard->MspInitCallback = HAL_SMARTCARD_MspInit; /* Legacy weak MspInitCallback */
+ break;
+
+ case HAL_SMARTCARD_MSPDEINIT_CB_ID :
+ hsmartcard->MspDeInitCallback = HAL_SMARTCARD_MspDeInit; /* Legacy weak MspDeInitCallback */
+ break;
+
+ default :
+ /* Update the error code */
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_SMARTCARD_STATE_RESET == hsmartcard->gState)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SMARTCARD_MSPINIT_CB_ID :
+ hsmartcard->MspInitCallback = HAL_SMARTCARD_MspInit;
+ break;
+
+ case HAL_SMARTCARD_MSPDEINIT_CB_ID :
+ hsmartcard->MspDeInitCallback = HAL_SMARTCARD_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsmartcard);
+
+ return status;
+}
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup SMARTCARD_Exported_Functions_Group2 IO operation functions
+ * @brief SMARTCARD Transmit and Receive functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the SMARTCARD data transfers.
+
+ [..]
+ Smartcard is a single wire half duplex communication protocol.
+ The Smartcard interface is designed to support asynchronous protocol Smartcards as
+ defined in the ISO 7816-3 standard. The USART should be configured as:
+ (+) 8 bits plus parity: where M=1 and PCE=1 in the USART_CR1 register
+ (+) 1.5 stop bits when transmitting and receiving: where STOP=11 in the USART_CR2 register.
+
+ [..]
+ (+) There are two modes of transfer:
+ (++) Blocking mode: The communication is performed in polling mode.
+ The HAL status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) Non-Blocking mode: The communication is performed using Interrupts
+ or DMA, the relevant API's return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated SMARTCARD IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+ (++) The HAL_SMARTCARD_TxCpltCallback(), HAL_SMARTCARD_RxCpltCallback() user callbacks
+ will be executed respectively at the end of the Transmit or Receive process
+ The HAL_SMARTCARD_ErrorCallback() user callback will be executed when a communication
+ error is detected.
+
+ (+) Blocking mode APIs are :
+ (++) HAL_SMARTCARD_Transmit()
+ (++) HAL_SMARTCARD_Receive()
+
+ (+) Non Blocking mode APIs with Interrupt are :
+ (++) HAL_SMARTCARD_Transmit_IT()
+ (++) HAL_SMARTCARD_Receive_IT()
+ (++) HAL_SMARTCARD_IRQHandler()
+
+ (+) Non Blocking mode functions with DMA are :
+ (++) HAL_SMARTCARD_Transmit_DMA()
+ (++) HAL_SMARTCARD_Receive_DMA()
+
+ (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
+ (++) HAL_SMARTCARD_TxCpltCallback()
+ (++) HAL_SMARTCARD_RxCpltCallback()
+ (++) HAL_SMARTCARD_ErrorCallback()
+
+ [..]
+ (#) Non-Blocking mode transfers could be aborted using Abort API's :
+ (++) HAL_SMARTCARD_Abort()
+ (++) HAL_SMARTCARD_AbortTransmit()
+ (++) HAL_SMARTCARD_AbortReceive()
+ (++) HAL_SMARTCARD_Abort_IT()
+ (++) HAL_SMARTCARD_AbortTransmit_IT()
+ (++) HAL_SMARTCARD_AbortReceive_IT()
+
+ (#) For Abort services based on interrupts (HAL_SMARTCARD_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
+ (++) HAL_SMARTCARD_AbortCpltCallback()
+ (++) HAL_SMARTCARD_AbortTransmitCpltCallback()
+ (++) HAL_SMARTCARD_AbortReceiveCpltCallback()
+
+ (#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
+ Errors are handled as follows :
+ (++) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
+ to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
+ Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
+ and HAL_SMARTCARD_ErrorCallback() user callback is executed. Transfer is kept ongoing on SMARTCARD side.
+ If user wants to abort it, Abort services should be called by user.
+ (++) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
+ This concerns Frame Error in Interrupt mode tranmission, Overrun Error in Interrupt mode reception and all errors in DMA mode.
+ Error code is set to allow user to identify error type, and HAL_SMARTCARD_ErrorCallback() user callback is executed.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Send an amount of data in blocking mode.
+ * @note When FIFO mode is enabled, writing a data in the TDR register adds one
+ * data to the TXFIFO. Write operations to the TDR register are performed
+ * when TXFNF flag is set. From hardware perspective, TXFNF flag and
+ * TXE are mapped on the same bit-field.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD 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_SMARTCARD_Transmit(SMARTCARD_HandleTypeDef *hsmartcard, uint8_t *pData, uint16_t Size,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint8_t *ptmpdata = pData;
+
+ /* Check that a Tx process is not already ongoing */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ if ((ptmpdata == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY_TX;
+
+ /* Init tickstart for timeout management */
+ tickstart = HAL_GetTick();
+
+ /* Disable the Peripheral first to update mode for TX master */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+
+ /* Disable Rx, enable Tx */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_RE);
+ SET_BIT(hsmartcard->Instance->RQR, (uint16_t)SMARTCARD_RXDATA_FLUSH_REQUEST);
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_TE);
+
+ /* Enable the Peripheral */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+ hsmartcard->TxXferSize = Size;
+ hsmartcard->TxXferCount = Size;
+
+ while (hsmartcard->TxXferCount > 0U)
+ {
+ hsmartcard->TxXferCount--;
+ if (SMARTCARD_WaitOnFlagUntilTimeout(hsmartcard, SMARTCARD_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ hsmartcard->Instance->TDR = (uint8_t)(*ptmpdata & 0xFFU);
+ ptmpdata++;
+ }
+ if (SMARTCARD_WaitOnFlagUntilTimeout(hsmartcard, SMARTCARD_TRANSMISSION_COMPLETION_FLAG(hsmartcard), RESET, tickstart,
+ Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ /* Re-enable Rx at end of transmission if initial mode is Rx/Tx */
+ if (hsmartcard->Init.Mode == SMARTCARD_MODE_TX_RX)
+ {
+ /* Disable the Peripheral first to update modes */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_RE);
+ /* Enable the Peripheral */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+ }
+
+ /* At end of Tx process, restore hsmartcard->gState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @note When FIFO mode is enabled, the RXFNE flag is set as long as the RXFIFO
+ * is not empty. Read operations from the RDR register are performed when
+ * RXFNE flag is set. From hardware perspective, RXFNE flag and
+ * RXNE are mapped on the same bit-field.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD 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_SMARTCARD_Receive(SMARTCARD_HandleTypeDef *hsmartcard, uint8_t *pData, uint16_t Size,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint8_t *ptmpdata = pData;
+
+ /* Check that a Rx process is not already ongoing */
+ if (hsmartcard->RxState == HAL_SMARTCARD_STATE_READY)
+ {
+ if ((ptmpdata == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_BUSY_RX;
+
+ /* Init tickstart for timeout management */
+ tickstart = HAL_GetTick();
+
+ hsmartcard->RxXferSize = Size;
+ hsmartcard->RxXferCount = Size;
+
+ /* Check the remain data to be received */
+ while (hsmartcard->RxXferCount > 0U)
+ {
+ hsmartcard->RxXferCount--;
+
+ if (SMARTCARD_WaitOnFlagUntilTimeout(hsmartcard, SMARTCARD_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ *ptmpdata = (uint8_t)(hsmartcard->Instance->RDR & (uint8_t)0x00FF);
+ ptmpdata++;
+ }
+
+ /* At end of Rx process, restore hsmartcard->RxState to Ready */
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in interrupt mode.
+ * @note When FIFO mode is disabled, USART interrupt is generated whenever
+ * USART_TDR register is empty, i.e one interrupt per data to transmit.
+ * @note When FIFO mode is enabled, USART interrupt is generated whenever
+ * TXFIFO threshold reached. In that case the interrupt rate depends on
+ * TXFIFO threshold configuration.
+ * @note This function sets the hsmartcard->TxIsr function pointer according to
+ * the FIFO mode (data transmission processing depends on FIFO mode).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @param pData pointer to data buffer.
+ * @param Size amount of data to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsmartcard, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Tx process is not already ongoing */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY_TX;
+
+ hsmartcard->pTxBuffPtr = pData;
+ hsmartcard->TxXferSize = Size;
+ hsmartcard->TxXferCount = Size;
+ hsmartcard->TxISR = NULL;
+
+ /* Disable the Peripheral first to update mode for TX master */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+
+ /* Disable Rx, enable Tx */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_RE);
+ SET_BIT(hsmartcard->Instance->RQR, (uint16_t)SMARTCARD_RXDATA_FLUSH_REQUEST);
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_TE);
+
+ /* Enable the Peripheral */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+
+ /* Configure Tx interrupt processing */
+ if (hsmartcard->FifoMode == SMARTCARD_FIFOMODE_ENABLE)
+ {
+ /* Set the Tx ISR function pointer */
+ hsmartcard->TxISR = SMARTCARD_TxISR_FIFOEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ /* Enable the SMARTCARD Error Interrupt: (Frame error) */
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the TX FIFO threshold interrupt */
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_TXFTIE);
+ }
+ else
+ {
+ /* Set the Tx ISR function pointer */
+ hsmartcard->TxISR = SMARTCARD_TxISR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ /* Enable the SMARTCARD Error Interrupt: (Frame error) */
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the SMARTCARD Transmit Data Register Empty Interrupt */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in interrupt mode.
+ * @note When FIFO mode is disabled, USART interrupt is generated whenever
+ * USART_RDR register can be read, i.e one interrupt per data to receive.
+ * @note When FIFO mode is enabled, USART interrupt is generated whenever
+ * RXFIFO threshold reached. In that case the interrupt rate depends on
+ * RXFIFO threshold configuration.
+ * @note This function sets the hsmartcard->RxIsr function pointer according to
+ * the FIFO mode (data reception processing depends on FIFO mode).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @param pData pointer to data buffer.
+ * @param Size amount of data to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsmartcard, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Rx process is not already ongoing */
+ if (hsmartcard->RxState == HAL_SMARTCARD_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_BUSY_RX;
+
+ hsmartcard->pRxBuffPtr = pData;
+ hsmartcard->RxXferSize = Size;
+ hsmartcard->RxXferCount = Size;
+
+ /* Configure Rx interrupt processing */
+ if ((hsmartcard->FifoMode == SMARTCARD_FIFOMODE_ENABLE) && (Size >= hsmartcard->NbRxDataToProcess))
+ {
+ /* Set the Rx ISR function pointer */
+ hsmartcard->RxISR = SMARTCARD_RxISR_FIFOEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ /* Enable the SMARTCART Parity Error interrupt and RX FIFO Threshold interrupt */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_PEIE);
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_RXFTIE);
+ }
+ else
+ {
+ /* Set the Rx ISR function pointer */
+ hsmartcard->RxISR = SMARTCARD_RxISR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ /* Enable the SMARTCARD Parity Error and Data Register not empty Interrupts */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE);
+ }
+
+ /* Enable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in DMA mode.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @param pData pointer to data buffer.
+ * @param Size amount of data to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_Transmit_DMA(SMARTCARD_HandleTypeDef *hsmartcard, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Tx process is not already ongoing */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY_TX;
+
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+ hsmartcard->pTxBuffPtr = pData;
+ hsmartcard->TxXferSize = Size;
+ hsmartcard->TxXferCount = Size;
+
+ /* Disable the Peripheral first to update mode for TX master */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+
+ /* Disable Rx, enable Tx */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_RE);
+ SET_BIT(hsmartcard->Instance->RQR, (uint16_t)SMARTCARD_RXDATA_FLUSH_REQUEST);
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_TE);
+
+ /* Enable the Peripheral */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+
+ /* Set the SMARTCARD DMA transfer complete callback */
+ hsmartcard->hdmatx->XferCpltCallback = SMARTCARD_DMATransmitCplt;
+
+ /* Set the SMARTCARD error callback */
+ hsmartcard->hdmatx->XferErrorCallback = SMARTCARD_DMAError;
+
+ /* Set the DMA abort callback */
+ hsmartcard->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the SMARTCARD transmit DMA channel */
+ if (HAL_DMA_Start_IT(hsmartcard->hdmatx, (uint32_t)hsmartcard->pTxBuffPtr, (uint32_t)&hsmartcard->Instance->TDR,
+ Size) == HAL_OK)
+ {
+ /* Clear the TC flag in the ICR register */
+ CLEAR_BIT(hsmartcard->Instance->ICR, USART_ICR_TCCF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ /* Enable the UART Error Interrupt: (Frame error) */
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the DMA transfer for transmit request by setting the DMAT bit
+ in the SMARTCARD associated USART CR3 register */
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Set error code to DMA */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ /* Restore hsmartcard->State to ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in DMA mode.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @param pData pointer to data buffer.
+ * @param Size amount of data to be received.
+ * @note The SMARTCARD-associated USART parity is enabled (PCE = 1),
+ * the received data contain the parity bit (MSB position).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_Receive_DMA(SMARTCARD_HandleTypeDef *hsmartcard, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Rx process is not already ongoing */
+ if (hsmartcard->RxState == HAL_SMARTCARD_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_BUSY_RX;
+
+ hsmartcard->pRxBuffPtr = pData;
+ hsmartcard->RxXferSize = Size;
+
+ /* Set the SMARTCARD DMA transfer complete callback */
+ hsmartcard->hdmarx->XferCpltCallback = SMARTCARD_DMAReceiveCplt;
+
+ /* Set the SMARTCARD DMA error callback */
+ hsmartcard->hdmarx->XferErrorCallback = SMARTCARD_DMAError;
+
+ /* Set the DMA abort callback */
+ hsmartcard->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hsmartcard->hdmarx, (uint32_t)&hsmartcard->Instance->RDR, (uint32_t)hsmartcard->pRxBuffPtr,
+ Size) == HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ /* Enable the SMARTCARD Parity Error Interrupt */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_PEIE);
+
+ /* Enable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the DMA transfer for the receiver request by setting the DMAR bit
+ in the SMARTCARD associated USART CR3 register */
+ SET_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAR);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Set error code to DMA */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ /* Restore hsmartcard->State to ready */
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Abort ongoing transfers (blocking mode).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable SMARTCARD Interrupts (Tx and Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_Abort(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Disable RTOIE, EOBIE, TXEIE, TCIE, RXNE, PE, RXFT, TXFT and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hsmartcard->Instance->CR1,
+ (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE | USART_CR1_RTOIE |
+ USART_CR1_EOBIE));
+ CLEAR_BIT(hsmartcard->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE));
+
+ /* Disable the SMARTCARD DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */
+ if (hsmartcard->hdmatx != NULL)
+ {
+ /* Set the SMARTCARD DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ hsmartcard->hdmatx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(hsmartcard->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hsmartcard->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Disable the SMARTCARD DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */
+ if (hsmartcard->hdmarx != NULL)
+ {
+ /* Set the SMARTCARD DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ hsmartcard->hdmarx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(hsmartcard->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hsmartcard->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Tx and Rx transfer counters */
+ hsmartcard->TxXferCount = 0U;
+ hsmartcard->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard,
+ SMARTCARD_CLEAR_OREF | SMARTCARD_CLEAR_NEF | SMARTCARD_CLEAR_PEF | SMARTCARD_CLEAR_FEF | SMARTCARD_CLEAR_RTOF |
+ SMARTCARD_CLEAR_EOBF);
+
+ /* Restore hsmartcard->gState and hsmartcard->RxState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ /* Reset Handle ErrorCode to No Error */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Transmit transfer (blocking mode).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable SMARTCARD Interrupts (Tx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_AbortTransmit(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Disable TCIE, TXEIE and TXFTIE interrupts */
+ CLEAR_BIT(hsmartcard->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_TXFTIE);
+
+ /* Check if a receive process is ongoing or not. If not disable ERR IT */
+ if (hsmartcard->RxState == HAL_SMARTCARD_STATE_READY)
+ {
+ /* Disable the SMARTCARD Error Interrupt: (Frame error) */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+ }
+
+ /* Disable the SMARTCARD DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */
+ if (hsmartcard->hdmatx != NULL)
+ {
+ /* Set the SMARTCARD DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ hsmartcard->hdmatx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(hsmartcard->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hsmartcard->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Tx transfer counter */
+ hsmartcard->TxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard, SMARTCARD_CLEAR_FEF);
+
+ /* Restore hsmartcard->gState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Receive transfer (blocking mode).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable SMARTCARD Interrupts (Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_AbortReceive(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Disable RTOIE, EOBIE, RXNE, PE, RXFT, TXFT and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hsmartcard->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_RTOIE | USART_CR1_EOBIE));
+ CLEAR_BIT(hsmartcard->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE));
+
+ /* Check if a Transmit process is ongoing or not. If not disable ERR IT */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ /* Disable the SMARTCARD Error Interrupt: (Frame error) */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+ }
+
+ /* Disable the SMARTCARD DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */
+ if (hsmartcard->hdmarx != NULL)
+ {
+ /* Set the SMARTCARD DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ hsmartcard->hdmarx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(hsmartcard->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hsmartcard->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Rx transfer counter */
+ hsmartcard->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard,
+ SMARTCARD_CLEAR_OREF | SMARTCARD_CLEAR_NEF | SMARTCARD_CLEAR_PEF | SMARTCARD_CLEAR_FEF | SMARTCARD_CLEAR_RTOF |
+ SMARTCARD_CLEAR_EOBF);
+
+ /* Restore hsmartcard->RxState to Ready */
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing transfers (Interrupt mode).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable SMARTCARD Interrupts (Tx and Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_Abort_IT(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ uint32_t abortcplt = 1U;
+
+ /* Disable RTOIE, EOBIE, TXEIE, TCIE, RXNE, PE, RXFT, TXFT and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hsmartcard->Instance->CR1,
+ (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE | USART_CR1_RTOIE |
+ USART_CR1_EOBIE));
+ CLEAR_BIT(hsmartcard->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE));
+
+ /* If DMA Tx and/or DMA Rx Handles are associated to SMARTCARD Handle, DMA Abort complete callbacks should be initialised
+ before any call to DMA Abort functions */
+ /* DMA Tx Handle is valid */
+ if (hsmartcard->hdmatx != NULL)
+ {
+ /* Set DMA Abort Complete callback if SMARTCARD DMA Tx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAT))
+ {
+ hsmartcard->hdmatx->XferAbortCallback = SMARTCARD_DMATxAbortCallback;
+ }
+ else
+ {
+ hsmartcard->hdmatx->XferAbortCallback = NULL;
+ }
+ }
+ /* DMA Rx Handle is valid */
+ if (hsmartcard->hdmarx != NULL)
+ {
+ /* Set DMA Abort Complete callback if SMARTCARD DMA Rx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAR))
+ {
+ hsmartcard->hdmarx->XferAbortCallback = SMARTCARD_DMARxAbortCallback;
+ }
+ else
+ {
+ hsmartcard->hdmarx->XferAbortCallback = NULL;
+ }
+ }
+
+ /* Disable the SMARTCARD DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAT))
+ {
+ /* Disable DMA Tx at UART level */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the SMARTCARD DMA Tx channel : use non blocking DMA Abort API (callback) */
+ if (hsmartcard->hdmatx != NULL)
+ {
+ /* SMARTCARD Tx DMA Abort callback has already been initialised :
+ will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hsmartcard->hdmatx) != HAL_OK)
+ {
+ hsmartcard->hdmatx->XferAbortCallback = NULL;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+
+ /* Disable the SMARTCARD DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the SMARTCARD DMA Rx channel : use non blocking DMA Abort API (callback) */
+ if (hsmartcard->hdmarx != NULL)
+ {
+ /* SMARTCARD Rx DMA Abort callback has already been initialised :
+ will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hsmartcard->hdmarx) != HAL_OK)
+ {
+ hsmartcard->hdmarx->XferAbortCallback = NULL;
+ abortcplt = 1U;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+
+ /* if no DMA abort complete callback execution is required => call user Abort Complete callback */
+ if (abortcplt == 1U)
+ {
+ /* Reset Tx and Rx transfer counters */
+ hsmartcard->TxXferCount = 0U;
+ hsmartcard->RxXferCount = 0U;
+
+ /* Clear ISR function pointers */
+ hsmartcard->RxISR = NULL;
+ hsmartcard->TxISR = NULL;
+
+ /* Reset errorCode */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard,
+ SMARTCARD_CLEAR_OREF | SMARTCARD_CLEAR_NEF | SMARTCARD_CLEAR_PEF | SMARTCARD_CLEAR_FEF | SMARTCARD_CLEAR_RTOF |
+ SMARTCARD_CLEAR_EOBF);
+
+ /* Restore hsmartcard->gState and hsmartcard->RxState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort complete callback */
+ hsmartcard->AbortCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Abort complete callback */
+ HAL_SMARTCARD_AbortCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Transmit transfer (Interrupt mode).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable SMARTCARD Interrupts (Tx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_AbortTransmit_IT(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Disable TCIE, TXEIE and TXFTIE interrupts */
+ CLEAR_BIT(hsmartcard->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_TXFTIE);
+
+ /* Check if a receive process is ongoing or not. If not disable ERR IT */
+ if (hsmartcard->RxState == HAL_SMARTCARD_STATE_READY)
+ {
+ /* Disable the SMARTCARD Error Interrupt: (Frame error) */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+ }
+
+ /* Disable the SMARTCARD DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the SMARTCARD DMA Tx channel : use non blocking DMA Abort API (callback) */
+ if (hsmartcard->hdmatx != NULL)
+ {
+ /* Set the SMARTCARD DMA Abort callback :
+ will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
+ hsmartcard->hdmatx->XferAbortCallback = SMARTCARD_DMATxOnlyAbortCallback;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hsmartcard->hdmatx) != HAL_OK)
+ {
+ /* Call Directly hsmartcard->hdmatx->XferAbortCallback function in case of error */
+ hsmartcard->hdmatx->XferAbortCallback(hsmartcard->hdmatx);
+ }
+ }
+ else
+ {
+ /* Reset Tx transfer counter */
+ hsmartcard->TxXferCount = 0U;
+
+ /* Clear TxISR function pointers */
+ hsmartcard->TxISR = NULL;
+
+ /* Restore hsmartcard->gState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Transmit Complete Callback */
+ hsmartcard->AbortTransmitCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Abort Transmit Complete Callback */
+ HAL_SMARTCARD_AbortTransmitCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+ /* Reset Tx transfer counter */
+ hsmartcard->TxXferCount = 0U;
+
+ /* Clear TxISR function pointers */
+ hsmartcard->TxISR = NULL;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard, SMARTCARD_CLEAR_FEF);
+
+ /* Restore hsmartcard->gState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Transmit Complete Callback */
+ hsmartcard->AbortTransmitCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Abort Transmit Complete Callback */
+ HAL_SMARTCARD_AbortTransmitCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Receive transfer (Interrupt mode).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable SMARTCARD Interrupts (Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARD_AbortReceive_IT(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Disable RTOIE, EOBIE, RXNE, PE, RXFT and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hsmartcard->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_RTOIE | USART_CR1_EOBIE));
+ CLEAR_BIT(hsmartcard->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE));
+
+ /* Check if a Transmit process is ongoing or not. If not disable ERR IT */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ /* Disable the SMARTCARD Error Interrupt: (Frame error) */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+ }
+
+ /* Disable the SMARTCARD DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the SMARTCARD DMA Rx channel : use non blocking DMA Abort API (callback) */
+ if (hsmartcard->hdmarx != NULL)
+ {
+ /* Set the SMARTCARD DMA Abort callback :
+ will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
+ hsmartcard->hdmarx->XferAbortCallback = SMARTCARD_DMARxOnlyAbortCallback;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hsmartcard->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hsmartcard->hdmarx->XferAbortCallback function in case of error */
+ hsmartcard->hdmarx->XferAbortCallback(hsmartcard->hdmarx);
+ }
+ }
+ else
+ {
+ /* Reset Rx transfer counter */
+ hsmartcard->RxXferCount = 0U;
+
+ /* Clear RxISR function pointer */
+ hsmartcard->RxISR = NULL;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard,
+ SMARTCARD_CLEAR_OREF | SMARTCARD_CLEAR_NEF | SMARTCARD_CLEAR_PEF | SMARTCARD_CLEAR_FEF | SMARTCARD_CLEAR_RTOF |
+ SMARTCARD_CLEAR_EOBF);
+
+ /* Restore hsmartcard->RxState to Ready */
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Receive Complete Callback */
+ hsmartcard->AbortReceiveCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Abort Receive Complete Callback */
+ HAL_SMARTCARD_AbortReceiveCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+ /* Reset Rx transfer counter */
+ hsmartcard->RxXferCount = 0U;
+
+ /* Clear RxISR function pointer */
+ hsmartcard->RxISR = NULL;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard,
+ SMARTCARD_CLEAR_OREF | SMARTCARD_CLEAR_NEF | SMARTCARD_CLEAR_PEF | SMARTCARD_CLEAR_FEF | SMARTCARD_CLEAR_RTOF |
+ SMARTCARD_CLEAR_EOBF);
+
+ /* Restore hsmartcard->RxState to Ready */
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Receive Complete Callback */
+ hsmartcard->AbortReceiveCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Abort Receive Complete Callback */
+ HAL_SMARTCARD_AbortReceiveCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle SMARTCARD interrupt requests.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+void HAL_SMARTCARD_IRQHandler(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ uint32_t isrflags = READ_REG(hsmartcard->Instance->ISR);
+ uint32_t cr1its = READ_REG(hsmartcard->Instance->CR1);
+ uint32_t cr3its = READ_REG(hsmartcard->Instance->CR3);
+ uint32_t errorflags;
+ uint32_t errorcode;
+
+ /* If no error occurs */
+ errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE | USART_ISR_RTOF));
+ if (errorflags == 0U)
+ {
+ /* SMARTCARD in mode Receiver ---------------------------------------------------*/
+ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
+ && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
+ || ((cr3its & USART_CR3_RXFTIE) != 0U)))
+ {
+ if (hsmartcard->RxISR != NULL)
+ {
+ hsmartcard->RxISR(hsmartcard);
+ }
+ return;
+ }
+ }
+
+ /* If some errors occur */
+ if ((errorflags != 0U)
+ && ((((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != 0U)
+ || ((cr1its & (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)) != 0U))))
+ {
+ /* SMARTCARD parity error interrupt occurred -------------------------------------*/
+ if (((isrflags & USART_ISR_PE) != 0U) && ((cr1its & USART_CR1_PEIE) != 0U))
+ {
+ __HAL_SMARTCARD_CLEAR_IT(hsmartcard, SMARTCARD_CLEAR_PEF);
+
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_PE;
+ }
+
+ /* SMARTCARD frame error interrupt occurred --------------------------------------*/
+ if (((isrflags & USART_ISR_FE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
+ {
+ __HAL_SMARTCARD_CLEAR_IT(hsmartcard, SMARTCARD_CLEAR_FEF);
+
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_FE;
+ }
+
+ /* SMARTCARD noise error interrupt occurred --------------------------------------*/
+ if (((isrflags & USART_ISR_NE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
+ {
+ __HAL_SMARTCARD_CLEAR_IT(hsmartcard, SMARTCARD_CLEAR_NEF);
+
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_NE;
+ }
+
+ /* SMARTCARD Over-Run interrupt occurred -----------------------------------------*/
+ if (((isrflags & USART_ISR_ORE) != 0U)
+ && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
+ || ((cr3its & USART_CR3_RXFTIE) != 0U)
+ || ((cr3its & USART_CR3_EIE) != 0U)))
+ {
+ __HAL_SMARTCARD_CLEAR_IT(hsmartcard, SMARTCARD_CLEAR_OREF);
+
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_ORE;
+ }
+
+ /* SMARTCARD receiver timeout interrupt occurred -----------------------------------------*/
+ if (((isrflags & USART_ISR_RTOF) != 0U) && ((cr1its & USART_CR1_RTOIE) != 0U))
+ {
+ __HAL_SMARTCARD_CLEAR_IT(hsmartcard, SMARTCARD_CLEAR_RTOF);
+
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_RTO;
+ }
+
+ /* Call SMARTCARD Error Call back function if need be --------------------------*/
+ if (hsmartcard->ErrorCode != HAL_SMARTCARD_ERROR_NONE)
+ {
+ /* SMARTCARD in mode Receiver ---------------------------------------------------*/
+ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
+ && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
+ || ((cr3its & USART_CR3_RXFTIE) != 0U)))
+ {
+ if (hsmartcard->RxISR != NULL)
+ {
+ hsmartcard->RxISR(hsmartcard);
+ }
+ }
+
+ /* If Error is to be considered as blocking :
+ - Receiver Timeout error in Reception
+ - Overrun error in Reception
+ - any error occurs in DMA mode reception
+ */
+ errorcode = hsmartcard->ErrorCode;
+ if ((HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAR))
+ || ((errorcode & (HAL_SMARTCARD_ERROR_RTO | HAL_SMARTCARD_ERROR_ORE)) != 0U))
+ {
+ /* Blocking error : transfer is aborted
+ Set the SMARTCARD state ready to be able to start again the process,
+ Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
+ SMARTCARD_EndRxTransfer(hsmartcard);
+
+ /* Disable the SMARTCARD DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the SMARTCARD DMA Rx channel */
+ if (hsmartcard->hdmarx != NULL)
+ {
+ /* Set the SMARTCARD DMA Abort callback :
+ will lead to call HAL_SMARTCARD_ErrorCallback() at end of DMA abort procedure */
+ hsmartcard->hdmarx->XferAbortCallback = SMARTCARD_DMAAbortOnError;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hsmartcard->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hsmartcard->hdmarx->XferAbortCallback function in case of error */
+ hsmartcard->hdmarx->XferAbortCallback(hsmartcard->hdmarx);
+ }
+ }
+ else
+ {
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hsmartcard->ErrorCallback(hsmartcard);
+#else
+ /* Call legacy weak user error callback */
+ HAL_SMARTCARD_ErrorCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hsmartcard->ErrorCallback(hsmartcard);
+#else
+ /* Call legacy weak user error callback */
+ HAL_SMARTCARD_ErrorCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+ }
+ /* other error type to be considered as blocking :
+ - Frame error in Transmission
+ */
+ else if ((hsmartcard->gState == HAL_SMARTCARD_STATE_BUSY_TX)
+ && ((errorcode & HAL_SMARTCARD_ERROR_FE) != 0U))
+ {
+ /* Blocking error : transfer is aborted
+ Set the SMARTCARD state ready to be able to start again the process,
+ Disable Tx Interrupts, and disable Tx DMA request, if ongoing */
+ SMARTCARD_EndTxTransfer(hsmartcard);
+
+ /* Disable the SMARTCARD DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the SMARTCARD DMA Tx channel */
+ if (hsmartcard->hdmatx != NULL)
+ {
+ /* Set the SMARTCARD DMA Abort callback :
+ will lead to call HAL_SMARTCARD_ErrorCallback() at end of DMA abort procedure */
+ hsmartcard->hdmatx->XferAbortCallback = SMARTCARD_DMAAbortOnError;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hsmartcard->hdmatx) != HAL_OK)
+ {
+ /* Call Directly hsmartcard->hdmatx->XferAbortCallback function in case of error */
+ hsmartcard->hdmatx->XferAbortCallback(hsmartcard->hdmatx);
+ }
+ }
+ else
+ {
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hsmartcard->ErrorCallback(hsmartcard);
+#else
+ /* Call legacy weak user error callback */
+ HAL_SMARTCARD_ErrorCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hsmartcard->ErrorCallback(hsmartcard);
+#else
+ /* Call legacy weak user error callback */
+ HAL_SMARTCARD_ErrorCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+ /* Non Blocking error : transfer could go on.
+ Error is notified to user through user error callback */
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hsmartcard->ErrorCallback(hsmartcard);
+#else
+ /* Call legacy weak user error callback */
+ HAL_SMARTCARD_ErrorCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+ }
+ }
+ return;
+
+ } /* End if some error occurs */
+
+ /* SMARTCARD in mode Receiver, end of block interruption ------------------------*/
+ if (((isrflags & USART_ISR_EOBF) != 0U) && ((cr1its & USART_CR1_EOBIE) != 0U))
+ {
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+ __HAL_UNLOCK(hsmartcard);
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx complete callback */
+ hsmartcard->RxCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Rx complete callback */
+ HAL_SMARTCARD_RxCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ /* Clear EOBF interrupt after HAL_SMARTCARD_RxCpltCallback() call for the End of Block information
+ to be available during HAL_SMARTCARD_RxCpltCallback() processing */
+ __HAL_SMARTCARD_CLEAR_IT(hsmartcard, SMARTCARD_CLEAR_EOBF);
+ return;
+ }
+
+ /* SMARTCARD in mode Transmitter ------------------------------------------------*/
+ if (((isrflags & USART_ISR_TXE_TXFNF) != 0U)
+ && (((cr1its & USART_CR1_TXEIE_TXFNFIE) != 0U)
+ || ((cr3its & USART_CR3_TXFTIE) != 0U)))
+ {
+ if (hsmartcard->TxISR != NULL)
+ {
+ hsmartcard->TxISR(hsmartcard);
+ }
+ return;
+ }
+
+ /* SMARTCARD in mode Transmitter (transmission end) ------------------------*/
+ if (__HAL_SMARTCARD_GET_IT(hsmartcard, hsmartcard->AdvancedInit.TxCompletionIndication) != RESET)
+ {
+ if (__HAL_SMARTCARD_GET_IT_SOURCE(hsmartcard, hsmartcard->AdvancedInit.TxCompletionIndication) != RESET)
+ {
+ SMARTCARD_EndTransmit_IT(hsmartcard);
+ return;
+ }
+ }
+
+ /* SMARTCARD TX Fifo Empty occurred ----------------------------------------------*/
+ if (((isrflags & USART_ISR_TXFE) != 0U) && ((cr1its & USART_CR1_TXFEIE) != 0U))
+ {
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Fifo Empty Callback */
+ hsmartcard->TxFifoEmptyCallback(hsmartcard);
+#else
+ /* Call legacy weak Tx Fifo Empty Callback */
+ HAL_SMARTCARDEx_TxFifoEmptyCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ return;
+ }
+
+ /* SMARTCARD RX Fifo Full occurred ----------------------------------------------*/
+ if (((isrflags & USART_ISR_RXFF) != 0U) && ((cr1its & USART_CR1_RXFFIE) != 0U))
+ {
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Fifo Full Callback */
+ hsmartcard->RxFifoFullCallback(hsmartcard);
+#else
+ /* Call legacy weak Rx Fifo Full Callback */
+ HAL_SMARTCARDEx_RxFifoFullCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ return;
+ }
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARD_TxCpltCallback(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARD_TxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARD_RxCpltCallback(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARD_RxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief SMARTCARD error callback.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARD_ErrorCallback(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARD_ErrorCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief SMARTCARD Abort Complete callback.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARD_AbortCpltCallback(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARD_AbortCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief SMARTCARD Abort Complete callback.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARD_AbortTransmitCpltCallback(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARD_AbortTransmitCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief SMARTCARD Abort Receive Complete callback.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARD_AbortReceiveCpltCallback(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARD_AbortReceiveCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SMARTCARD_Exported_Functions_Group4 Peripheral State and Errors functions
+ * @brief SMARTCARD State and Errors functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Errors functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to return the State of SmartCard
+ handle and also return Peripheral Errors occurred during communication process
+ (+) HAL_SMARTCARD_GetState() API can be helpful to check in run-time the state
+ of the SMARTCARD peripheral.
+ (+) HAL_SMARTCARD_GetError() checks in run-time errors that could occur during
+ communication.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the SMARTCARD handle state.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval SMARTCARD handle state
+ */
+HAL_SMARTCARD_StateTypeDef HAL_SMARTCARD_GetState(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Return SMARTCARD handle state */
+ uint32_t temp1;
+ uint32_t temp2;
+ temp1 = (uint32_t)hsmartcard->gState;
+ temp2 = (uint32_t)hsmartcard->RxState;
+
+ return (HAL_SMARTCARD_StateTypeDef)(temp1 | temp2);
+}
+
+/**
+ * @brief Return the SMARTCARD handle error code.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval SMARTCARD handle Error Code
+ */
+uint32_t HAL_SMARTCARD_GetError(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ return hsmartcard->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup SMARTCARD_Private_Functions SMARTCARD Private Functions
+ * @{
+ */
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Initialize the callbacks to their default values.
+ * @param hsmartcard SMARTCARD handle.
+ * @retval none
+ */
+void SMARTCARD_InitCallbacksToDefault(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Init the SMARTCARD Callback settings */
+ hsmartcard->TxCpltCallback = HAL_SMARTCARD_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ hsmartcard->RxCpltCallback = HAL_SMARTCARD_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ hsmartcard->ErrorCallback = HAL_SMARTCARD_ErrorCallback; /* Legacy weak ErrorCallback */
+ hsmartcard->AbortCpltCallback = HAL_SMARTCARD_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ hsmartcard->AbortTransmitCpltCallback = HAL_SMARTCARD_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
+ hsmartcard->AbortReceiveCpltCallback = HAL_SMARTCARD_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
+ hsmartcard->RxFifoFullCallback = HAL_SMARTCARDEx_RxFifoFullCallback; /* Legacy weak RxFifoFullCallback */
+ hsmartcard->TxFifoEmptyCallback = HAL_SMARTCARDEx_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */
+
+}
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
+
+/**
+ * @brief Configure the SMARTCARD associated USART peripheral.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SMARTCARD_SetConfig(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ uint32_t tmpreg;
+ SMARTCARD_ClockSourceTypeDef clocksource;
+ HAL_StatusTypeDef ret = HAL_OK;
+ const uint16_t SMARTCARDPrescTable[12] = {1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U};
+ PLL2_ClocksTypeDef pll2_clocks;
+ PLL3_ClocksTypeDef pll3_clocks;
+ uint32_t pclk;
+
+ /* Check the parameters */
+ assert_param(IS_SMARTCARD_INSTANCE(hsmartcard->Instance));
+ assert_param(IS_SMARTCARD_BAUDRATE(hsmartcard->Init.BaudRate));
+ assert_param(IS_SMARTCARD_WORD_LENGTH(hsmartcard->Init.WordLength));
+ assert_param(IS_SMARTCARD_STOPBITS(hsmartcard->Init.StopBits));
+ assert_param(IS_SMARTCARD_PARITY(hsmartcard->Init.Parity));
+ assert_param(IS_SMARTCARD_MODE(hsmartcard->Init.Mode));
+ assert_param(IS_SMARTCARD_POLARITY(hsmartcard->Init.CLKPolarity));
+ assert_param(IS_SMARTCARD_PHASE(hsmartcard->Init.CLKPhase));
+ assert_param(IS_SMARTCARD_LASTBIT(hsmartcard->Init.CLKLastBit));
+ assert_param(IS_SMARTCARD_ONE_BIT_SAMPLE(hsmartcard->Init.OneBitSampling));
+ assert_param(IS_SMARTCARD_NACK(hsmartcard->Init.NACKEnable));
+ assert_param(IS_SMARTCARD_TIMEOUT(hsmartcard->Init.TimeOutEnable));
+ assert_param(IS_SMARTCARD_AUTORETRY_COUNT(hsmartcard->Init.AutoRetryCount));
+ assert_param(IS_SMARTCARD_CLOCKPRESCALER(hsmartcard->Init.ClockPrescaler));
+
+ /*-------------------------- USART CR1 Configuration -----------------------*/
+ /* In SmartCard mode, M and PCE are forced to 1 (8 bits + parity).
+ * Oversampling is forced to 16 (OVER8 = 0).
+ * Configure the Parity and Mode:
+ * set PS bit according to hsmartcard->Init.Parity value
+ * set TE and RE bits according to hsmartcard->Init.Mode value */
+ tmpreg = (uint32_t) hsmartcard->Init.Parity | hsmartcard->Init.Mode;
+ tmpreg |= (uint32_t) hsmartcard->Init.WordLength | hsmartcard->FifoMode;
+ MODIFY_REG(hsmartcard->Instance->CR1, USART_CR1_FIELDS, tmpreg);
+
+ /*-------------------------- USART CR2 Configuration -----------------------*/
+ tmpreg = hsmartcard->Init.StopBits;
+ /* Synchronous mode is activated by default */
+ tmpreg |= (uint32_t) USART_CR2_CLKEN | hsmartcard->Init.CLKPolarity;
+ tmpreg |= (uint32_t) hsmartcard->Init.CLKPhase | hsmartcard->Init.CLKLastBit;
+ tmpreg |= (uint32_t) hsmartcard->Init.TimeOutEnable;
+ MODIFY_REG(hsmartcard->Instance->CR2, USART_CR2_FIELDS, tmpreg);
+
+ /*-------------------------- USART CR3 Configuration -----------------------*/
+ /* Configure
+ * - one-bit sampling method versus three samples' majority rule
+ * according to hsmartcard->Init.OneBitSampling
+ * - NACK transmission in case of parity error according
+ * to hsmartcard->Init.NACKEnable
+ * - autoretry counter according to hsmartcard->Init.AutoRetryCount */
+
+ tmpreg = (uint32_t) hsmartcard->Init.OneBitSampling | hsmartcard->Init.NACKEnable;
+ tmpreg |= ((uint32_t)hsmartcard->Init.AutoRetryCount << USART_CR3_SCARCNT_Pos);
+ MODIFY_REG(hsmartcard->Instance->CR3, USART_CR3_FIELDS, tmpreg);
+
+ /*--------------------- SMARTCARD clock PRESC Configuration ----------------*/
+ /* Configure
+ * - SMARTCARD Clock Prescaler: set PRESCALER according to hsmartcard->Init.ClockPrescaler value */
+ MODIFY_REG(hsmartcard->Instance->PRESC, USART_PRESC_PRESCALER, hsmartcard->Init.ClockPrescaler);
+
+ /*-------------------------- USART GTPR Configuration ----------------------*/
+ tmpreg = (hsmartcard->Init.Prescaler | ((uint32_t)hsmartcard->Init.GuardTime << USART_GTPR_GT_Pos));
+ MODIFY_REG(hsmartcard->Instance->GTPR, (uint16_t)(USART_GTPR_GT | USART_GTPR_PSC), (uint16_t)tmpreg);
+
+ /*-------------------------- USART RTOR Configuration ----------------------*/
+ tmpreg = ((uint32_t)hsmartcard->Init.BlockLength << USART_RTOR_BLEN_Pos);
+ if (hsmartcard->Init.TimeOutEnable == SMARTCARD_TIMEOUT_ENABLE)
+ {
+ assert_param(IS_SMARTCARD_TIMEOUT_VALUE(hsmartcard->Init.TimeOutValue));
+ tmpreg |= (uint32_t) hsmartcard->Init.TimeOutValue;
+ }
+ MODIFY_REG(hsmartcard->Instance->RTOR, (USART_RTOR_RTO | USART_RTOR_BLEN), tmpreg);
+
+ /*-------------------------- USART BRR Configuration -----------------------*/
+ SMARTCARD_GETCLOCKSOURCE(hsmartcard, clocksource);
+ tmpreg = 0U;
+ switch (clocksource)
+ {
+ case SMARTCARD_CLOCKSOURCE_D2PCLK1:
+ pclk = HAL_RCC_GetPCLK1Freq();
+ tmpreg = (uint16_t)(((pclk / SMARTCARDPrescTable[hsmartcard->Init.ClockPrescaler]) + (hsmartcard->Init.BaudRate / 2U)) / hsmartcard->Init.BaudRate);
+ break;
+ case SMARTCARD_CLOCKSOURCE_D2PCLK2:
+ pclk = HAL_RCC_GetPCLK2Freq();
+ tmpreg = (uint16_t)(((pclk / SMARTCARDPrescTable[hsmartcard->Init.ClockPrescaler]) + (hsmartcard->Init.BaudRate / 2U)) / hsmartcard->Init.BaudRate);
+ break;
+ case SMARTCARD_CLOCKSOURCE_PLL2Q:
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ tmpreg = (uint16_t)(((pll2_clocks.PLL2_Q_Frequency / SMARTCARDPrescTable[hsmartcard->Init.ClockPrescaler]) + (hsmartcard->Init.BaudRate / 2U)) / hsmartcard->Init.BaudRate);
+ break;
+ case SMARTCARD_CLOCKSOURCE_PLL3Q:
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ tmpreg = (uint16_t)(((pll3_clocks.PLL3_Q_Frequency / SMARTCARDPrescTable[hsmartcard->Init.ClockPrescaler]) + (hsmartcard->Init.BaudRate / 2U)) / hsmartcard->Init.BaudRate);
+ break;
+ case SMARTCARD_CLOCKSOURCE_HSI:
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ tmpreg = (uint16_t)((((HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3U)) / SMARTCARDPrescTable[hsmartcard->Init.ClockPrescaler]) + (hsmartcard->Init.BaudRate / 2U)) / hsmartcard->Init.BaudRate);
+ }
+ else
+ {
+ tmpreg = (uint16_t)(((HSI_VALUE / SMARTCARDPrescTable[hsmartcard->Init.ClockPrescaler]) + (hsmartcard->Init.BaudRate / 2U)) / hsmartcard->Init.BaudRate);
+ }
+ break;
+ case SMARTCARD_CLOCKSOURCE_CSI:
+ tmpreg = (uint16_t)(((CSI_VALUE / SMARTCARDPrescTable[hsmartcard->Init.ClockPrescaler]) + (hsmartcard->Init.BaudRate / 2U)) / hsmartcard->Init.BaudRate);
+ break;
+ case SMARTCARD_CLOCKSOURCE_LSE:
+ tmpreg = (uint16_t)(((uint16_t)(LSE_VALUE / SMARTCARDPrescTable[hsmartcard->Init.ClockPrescaler]) + (hsmartcard->Init.BaudRate / 2U)) / hsmartcard->Init.BaudRate);
+ break;
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ /* USARTDIV must be greater than or equal to 0d16 */
+ if ((tmpreg >= USART_BRR_MIN) && (tmpreg <= USART_BRR_MAX))
+ {
+ hsmartcard->Instance->BRR = tmpreg;
+ }
+ else
+ {
+ ret = HAL_ERROR;
+ }
+
+ /* Initialize the number of data to process during RX/TX ISR execution */
+ hsmartcard->NbTxDataToProcess = 1U;
+ hsmartcard->NbRxDataToProcess = 1U;
+
+ /* Clear ISR function pointers */
+ hsmartcard->RxISR = NULL;
+ hsmartcard->TxISR = NULL;
+
+ return ret;
+}
+
+
+/**
+ * @brief Configure the SMARTCARD associated USART peripheral advanced features.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+static void SMARTCARD_AdvFeatureConfig(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Check whether the set of advanced features to configure is properly set */
+ assert_param(IS_SMARTCARD_ADVFEATURE_INIT(hsmartcard->AdvancedInit.AdvFeatureInit));
+
+ /* if required, configure TX pin active level inversion */
+ if (HAL_IS_BIT_SET(hsmartcard->AdvancedInit.AdvFeatureInit, SMARTCARD_ADVFEATURE_TXINVERT_INIT))
+ {
+ assert_param(IS_SMARTCARD_ADVFEATURE_TXINV(hsmartcard->AdvancedInit.TxPinLevelInvert));
+ MODIFY_REG(hsmartcard->Instance->CR2, USART_CR2_TXINV, hsmartcard->AdvancedInit.TxPinLevelInvert);
+ }
+
+ /* if required, configure RX pin active level inversion */
+ if (HAL_IS_BIT_SET(hsmartcard->AdvancedInit.AdvFeatureInit, SMARTCARD_ADVFEATURE_RXINVERT_INIT))
+ {
+ assert_param(IS_SMARTCARD_ADVFEATURE_RXINV(hsmartcard->AdvancedInit.RxPinLevelInvert));
+ MODIFY_REG(hsmartcard->Instance->CR2, USART_CR2_RXINV, hsmartcard->AdvancedInit.RxPinLevelInvert);
+ }
+
+ /* if required, configure data inversion */
+ if (HAL_IS_BIT_SET(hsmartcard->AdvancedInit.AdvFeatureInit, SMARTCARD_ADVFEATURE_DATAINVERT_INIT))
+ {
+ assert_param(IS_SMARTCARD_ADVFEATURE_DATAINV(hsmartcard->AdvancedInit.DataInvert));
+ MODIFY_REG(hsmartcard->Instance->CR2, USART_CR2_DATAINV, hsmartcard->AdvancedInit.DataInvert);
+ }
+
+ /* if required, configure RX/TX pins swap */
+ if (HAL_IS_BIT_SET(hsmartcard->AdvancedInit.AdvFeatureInit, SMARTCARD_ADVFEATURE_SWAP_INIT))
+ {
+ assert_param(IS_SMARTCARD_ADVFEATURE_SWAP(hsmartcard->AdvancedInit.Swap));
+ MODIFY_REG(hsmartcard->Instance->CR2, USART_CR2_SWAP, hsmartcard->AdvancedInit.Swap);
+ }
+
+ /* if required, configure RX overrun detection disabling */
+ if (HAL_IS_BIT_SET(hsmartcard->AdvancedInit.AdvFeatureInit, SMARTCARD_ADVFEATURE_RXOVERRUNDISABLE_INIT))
+ {
+ assert_param(IS_SMARTCARD_OVERRUN(hsmartcard->AdvancedInit.OverrunDisable));
+ MODIFY_REG(hsmartcard->Instance->CR3, USART_CR3_OVRDIS, hsmartcard->AdvancedInit.OverrunDisable);
+ }
+
+ /* if required, configure DMA disabling on reception error */
+ if (HAL_IS_BIT_SET(hsmartcard->AdvancedInit.AdvFeatureInit, SMARTCARD_ADVFEATURE_DMADISABLEONERROR_INIT))
+ {
+ assert_param(IS_SMARTCARD_ADVFEATURE_DMAONRXERROR(hsmartcard->AdvancedInit.DMADisableonRxError));
+ MODIFY_REG(hsmartcard->Instance->CR3, USART_CR3_DDRE, hsmartcard->AdvancedInit.DMADisableonRxError);
+ }
+
+ /* if required, configure MSB first on communication line */
+ if (HAL_IS_BIT_SET(hsmartcard->AdvancedInit.AdvFeatureInit, SMARTCARD_ADVFEATURE_MSBFIRST_INIT))
+ {
+ assert_param(IS_SMARTCARD_ADVFEATURE_MSBFIRST(hsmartcard->AdvancedInit.MSBFirst));
+ MODIFY_REG(hsmartcard->Instance->CR2, USART_CR2_MSBFIRST, hsmartcard->AdvancedInit.MSBFirst);
+ }
+
+}
+
+/**
+ * @brief Check the SMARTCARD Idle State.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SMARTCARD_CheckIdleState(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ uint32_t tickstart;
+
+ /* Initialize the SMARTCARD ErrorCode */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+
+ /* Init tickstart for timeout management */
+ tickstart = HAL_GetTick();
+
+ /* Check if the Transmitter is enabled */
+ if ((hsmartcard->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE)
+ {
+ /* Wait until TEACK flag is set */
+ if (SMARTCARD_WaitOnFlagUntilTimeout(hsmartcard, USART_ISR_TEACK, RESET, tickstart,
+ SMARTCARD_TEACK_REACK_TIMEOUT) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Check if the Receiver is enabled */
+ if ((hsmartcard->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE)
+ {
+ /* Wait until REACK flag is set */
+ if (SMARTCARD_WaitOnFlagUntilTimeout(hsmartcard, USART_ISR_REACK, RESET, tickstart,
+ SMARTCARD_TEACK_REACK_TIMEOUT) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Initialize the SMARTCARD states */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle SMARTCARD Communication Timeout.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @param Flag Specifies the SMARTCARD flag to check.
+ * @param Status The new Flag status (SET or RESET).
+ * @param Tickstart Tick start value
+ * @param Timeout Timeout duration.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SMARTCARD_WaitOnFlagUntilTimeout(SMARTCARD_HandleTypeDef *hsmartcard, uint32_t Flag,
+ FlagStatus Status, uint32_t Tickstart, uint32_t Timeout)
+{
+ /* Wait until flag is set */
+ while ((__HAL_SMARTCARD_GET_FLAG(hsmartcard, Flag) ? SET : RESET) == Status)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ CLEAR_BIT(hsmartcard->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE));
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+
+/**
+ * @brief End ongoing Tx transfer on SMARTCARD peripheral (following error detection or Transmit completion).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+static void SMARTCARD_EndTxTransfer(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Disable TXEIE, TCIE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hsmartcard->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+
+ /* At end of Tx process, restore hsmartcard->gState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+}
+
+
+/**
+ * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion).
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+static void SMARTCARD_EndRxTransfer(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hsmartcard->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+
+ /* At end of Rx process, restore hsmartcard->RxState to Ready */
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+}
+
+
+/**
+ * @brief DMA SMARTCARD 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 SMARTCARD_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ SMARTCARD_HandleTypeDef *hsmartcard = (SMARTCARD_HandleTypeDef *)(hdma->Parent);
+ hsmartcard->TxXferCount = 0U;
+
+ /* Disable the DMA transfer for transmit request by resetting the DMAT bit
+ in the SMARTCARD associated USART CR3 register */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAT);
+
+ /* Enable the SMARTCARD Transmit Complete Interrupt */
+ __HAL_SMARTCARD_ENABLE_IT(hsmartcard, hsmartcard->AdvancedInit.TxCompletionIndication);
+}
+
+/**
+ * @brief DMA SMARTCARD 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 SMARTCARD_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SMARTCARD_HandleTypeDef *hsmartcard = (SMARTCARD_HandleTypeDef *)(hdma->Parent);
+ hsmartcard->RxXferCount = 0U;
+
+ /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_PEIE);
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the DMA transfer for the receiver request by resetting the DMAR bit
+ in the SMARTCARD associated USART CR3 register */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_DMAR);
+
+ /* At end of Rx process, restore hsmartcard->RxState to Ready */
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx complete callback */
+ hsmartcard->RxCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Rx complete callback */
+ HAL_SMARTCARD_RxCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief DMA SMARTCARD 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 SMARTCARD_DMAError(DMA_HandleTypeDef *hdma)
+{
+ SMARTCARD_HandleTypeDef *hsmartcard = (SMARTCARD_HandleTypeDef *)(hdma->Parent);
+
+ /* Stop SMARTCARD DMA Tx request if ongoing */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_BUSY_TX)
+ {
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAT))
+ {
+ hsmartcard->TxXferCount = 0U;
+ SMARTCARD_EndTxTransfer(hsmartcard);
+ }
+ }
+
+ /* Stop SMARTCARD DMA Rx request if ongoing */
+ if (hsmartcard->RxState == HAL_SMARTCARD_STATE_BUSY_RX)
+ {
+ if (HAL_IS_BIT_SET(hsmartcard->Instance->CR3, USART_CR3_DMAR))
+ {
+ hsmartcard->RxXferCount = 0U;
+ SMARTCARD_EndRxTransfer(hsmartcard);
+ }
+ }
+
+ hsmartcard->ErrorCode |= HAL_SMARTCARD_ERROR_DMA;
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hsmartcard->ErrorCallback(hsmartcard);
+#else
+ /* Call legacy weak user error callback */
+ HAL_SMARTCARD_ErrorCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief DMA SMARTCARD communication abort callback, when initiated by HAL services on Error
+ * (To be called at end of DMA Abort procedure following error occurrence).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SMARTCARD_DMAAbortOnError(DMA_HandleTypeDef *hdma)
+{
+ SMARTCARD_HandleTypeDef *hsmartcard = (SMARTCARD_HandleTypeDef *)(hdma->Parent);
+ hsmartcard->RxXferCount = 0U;
+ hsmartcard->TxXferCount = 0U;
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered user error callback */
+ hsmartcard->ErrorCallback(hsmartcard);
+#else
+ /* Call legacy weak user error callback */
+ HAL_SMARTCARD_ErrorCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief DMA SMARTCARD Tx communication abort callback, when initiated by user
+ * (To be called at end of DMA Tx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Rx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SMARTCARD_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ SMARTCARD_HandleTypeDef *hsmartcard = (SMARTCARD_HandleTypeDef *)(hdma->Parent);
+
+ hsmartcard->hdmatx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (hsmartcard->hdmarx != NULL)
+ {
+ if (hsmartcard->hdmarx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
+ hsmartcard->TxXferCount = 0U;
+ hsmartcard->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard,
+ SMARTCARD_CLEAR_OREF | SMARTCARD_CLEAR_NEF | SMARTCARD_CLEAR_PEF | SMARTCARD_CLEAR_FEF | SMARTCARD_CLEAR_RTOF |
+ SMARTCARD_CLEAR_EOBF);
+
+ /* Restore hsmartcard->gState and hsmartcard->RxState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort complete callback */
+ hsmartcard->AbortCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Abort complete callback */
+ HAL_SMARTCARD_AbortCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+}
+
+
+/**
+ * @brief DMA SMARTCARD Rx communication abort callback, when initiated by user
+ * (To be called at end of DMA Rx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Tx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SMARTCARD_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ SMARTCARD_HandleTypeDef *hsmartcard = (SMARTCARD_HandleTypeDef *)(hdma->Parent);
+
+ hsmartcard->hdmarx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (hsmartcard->hdmatx != NULL)
+ {
+ if (hsmartcard->hdmatx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
+ hsmartcard->TxXferCount = 0U;
+ hsmartcard->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ hsmartcard->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard,
+ SMARTCARD_CLEAR_OREF | SMARTCARD_CLEAR_NEF | SMARTCARD_CLEAR_PEF | SMARTCARD_CLEAR_FEF | SMARTCARD_CLEAR_RTOF |
+ SMARTCARD_CLEAR_EOBF);
+
+ /* Restore hsmartcard->gState and hsmartcard->RxState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort complete callback */
+ hsmartcard->AbortCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Abort complete callback */
+ HAL_SMARTCARD_AbortCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+}
+
+
+/**
+ * @brief DMA SMARTCARD Tx communication abort callback, when initiated by user by a call to
+ * HAL_SMARTCARD_AbortTransmit_IT API (Abort only Tx transfer)
+ * (This callback is executed at end of DMA Tx Abort procedure following user abort request,
+ * and leads to user Tx Abort Complete callback execution).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SMARTCARD_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ SMARTCARD_HandleTypeDef *hsmartcard = (SMARTCARD_HandleTypeDef *)(hdma->Parent);
+
+ hsmartcard->TxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard, SMARTCARD_CLEAR_FEF);
+
+ /* Restore hsmartcard->gState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Transmit Complete Callback */
+ hsmartcard->AbortTransmitCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Abort Transmit Complete Callback */
+ HAL_SMARTCARD_AbortTransmitCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief DMA SMARTCARD Rx communication abort callback, when initiated by user by a call to
+ * HAL_SMARTCARD_AbortReceive_IT API (Abort only Rx transfer)
+ * (This callback is executed at end of DMA Rx Abort procedure following user abort request,
+ * and leads to user Rx Abort Complete callback execution).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SMARTCARD_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ SMARTCARD_HandleTypeDef *hsmartcard = (SMARTCARD_HandleTypeDef *)(hdma->Parent);
+
+ hsmartcard->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_SMARTCARD_CLEAR_FLAG(hsmartcard,
+ SMARTCARD_CLEAR_OREF | SMARTCARD_CLEAR_NEF | SMARTCARD_CLEAR_PEF | SMARTCARD_CLEAR_FEF | SMARTCARD_CLEAR_RTOF |
+ SMARTCARD_CLEAR_EOBF);
+
+ /* Restore hsmartcard->RxState to Ready */
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Receive Complete Callback */
+ hsmartcard->AbortReceiveCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Abort Receive Complete Callback */
+ HAL_SMARTCARD_AbortReceiveCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief Send an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_SMARTCARD_Transmit_IT()
+ * and when the FIFO mode is disabled.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+static void SMARTCARD_TxISR(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Check that a Tx process is ongoing */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_BUSY_TX)
+ {
+ if (hsmartcard->TxXferCount == 0U)
+ {
+ /* Disable the SMARTCARD Transmit Data Register Empty Interrupt */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
+
+ /* Enable the SMARTCARD Transmit Complete Interrupt */
+ __HAL_SMARTCARD_ENABLE_IT(hsmartcard, hsmartcard->AdvancedInit.TxCompletionIndication);
+ }
+ else
+ {
+ hsmartcard->Instance->TDR = (uint8_t)(*hsmartcard->pTxBuffPtr & 0xFFU);
+ hsmartcard->pTxBuffPtr++;
+ hsmartcard->TxXferCount--;
+ }
+ }
+}
+
+/**
+ * @brief Send an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_SMARTCARD_Transmit_IT()
+ * and when the FIFO mode is enabled.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+static void SMARTCARD_TxISR_FIFOEN(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ uint16_t nb_tx_data;
+
+ /* Check that a Tx process is ongoing */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_BUSY_TX)
+ {
+ for (nb_tx_data = hsmartcard->NbTxDataToProcess ; nb_tx_data > 0U ; nb_tx_data--)
+ {
+ if (hsmartcard->TxXferCount == 0U)
+ {
+ /* Disable the SMARTCARD Transmit Data Register Empty Interrupt */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
+
+ /* Enable the SMARTCARD Transmit Complete Interrupt */
+ __HAL_SMARTCARD_ENABLE_IT(hsmartcard, hsmartcard->AdvancedInit.TxCompletionIndication);
+ }
+ else if (READ_BIT(hsmartcard->Instance->ISR, USART_ISR_TXE_TXFNF) != 0U)
+ {
+ hsmartcard->Instance->TDR = (uint8_t)(*hsmartcard->pTxBuffPtr & 0xFFU);
+ hsmartcard->pTxBuffPtr++;
+ hsmartcard->TxXferCount--;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+}
+
+/**
+ * @brief Wrap up transmission in non-blocking mode.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+static void SMARTCARD_EndTransmit_IT(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Disable the SMARTCARD Transmit Complete Interrupt */
+ __HAL_SMARTCARD_DISABLE_IT(hsmartcard, hsmartcard->AdvancedInit.TxCompletionIndication);
+
+ /* Check if a receive process is ongoing or not. If not disable ERR IT */
+ if (hsmartcard->RxState == HAL_SMARTCARD_STATE_READY)
+ {
+ /* Disable the SMARTCARD Error Interrupt: (Frame error) */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+ }
+
+ /* Re-enable Rx at end of transmission if initial mode is Rx/Tx */
+ if (hsmartcard->Init.Mode == SMARTCARD_MODE_TX_RX)
+ {
+ /* Disable the Peripheral first to update modes */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_RE);
+ /* Enable the Peripheral */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_UE);
+ }
+
+ /* Tx process is ended, restore hsmartcard->gState to Ready */
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* Clear TxISR function pointer */
+ hsmartcard->TxISR = NULL;
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx complete callback */
+ hsmartcard->TxCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Tx complete callback */
+ HAL_SMARTCARD_TxCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_SMARTCARD_Receive_IT()
+ * and when the FIFO mode is disabled.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+static void SMARTCARD_RxISR(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Check that a Rx process is ongoing */
+ if (hsmartcard->RxState == HAL_SMARTCARD_STATE_BUSY_RX)
+ {
+ *hsmartcard->pRxBuffPtr = (uint8_t)(hsmartcard->Instance->RDR & (uint8_t)0xFF);
+ hsmartcard->pRxBuffPtr++;
+
+ hsmartcard->RxXferCount--;
+ if (hsmartcard->RxXferCount == 0U)
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);
+
+ /* Check if a transmit process is ongoing or not. If not disable ERR IT */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ /* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+ }
+
+ /* Disable the SMARTCARD Parity Error Interrupt */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_PEIE);
+
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ /* Clear RxISR function pointer */
+ hsmartcard->RxISR = NULL;
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx complete callback */
+ hsmartcard->RxCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Rx complete callback */
+ HAL_SMARTCARD_RxCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_SMARTCARD_SEND_REQ(hsmartcard, SMARTCARD_RXDATA_FLUSH_REQUEST);
+ }
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_SMARTCARD_Receive_IT()
+ * and when the FIFO mode is enabled.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+static void SMARTCARD_RxISR_FIFOEN(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ uint16_t nb_rx_data;
+ uint16_t rxdatacount;
+
+ /* Check that a Rx process is ongoing */
+ if (hsmartcard->RxState == HAL_SMARTCARD_STATE_BUSY_RX)
+ {
+ for (nb_rx_data = hsmartcard->NbRxDataToProcess ; nb_rx_data > 0U ; nb_rx_data--)
+ {
+ *hsmartcard->pRxBuffPtr = (uint8_t)(hsmartcard->Instance->RDR & (uint8_t)0xFF);
+ hsmartcard->pRxBuffPtr++;
+
+ hsmartcard->RxXferCount--;
+ if (hsmartcard->RxXferCount == 0U)
+ {
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);
+
+ /* Check if a transmit process is ongoing or not. If not disable ERR IT */
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ /* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_EIE);
+ }
+
+ /* Disable the SMARTCARD Parity Error Interrupt */
+ CLEAR_BIT(hsmartcard->Instance->CR1, USART_CR1_PEIE);
+
+ hsmartcard->RxState = HAL_SMARTCARD_STATE_READY;
+
+ /* Clear RxISR function pointer */
+ hsmartcard->RxISR = NULL;
+
+#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx complete callback */
+ hsmartcard->RxCpltCallback(hsmartcard);
+#else
+ /* Call legacy weak Rx complete callback */
+ HAL_SMARTCARD_RxCpltCallback(hsmartcard);
+#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
+ }
+ }
+
+ /* When remaining number of bytes to receive is less than the RX FIFO
+ threshold, next incoming frames are processed as if FIFO mode was
+ disabled (i.e. one interrupt per received frame).
+ */
+ rxdatacount = hsmartcard->RxXferCount;
+ if (((rxdatacount != 0U)) && (rxdatacount < hsmartcard->NbRxDataToProcess))
+ {
+ /* Disable the UART RXFT interrupt*/
+ CLEAR_BIT(hsmartcard->Instance->CR3, USART_CR3_RXFTIE);
+
+ /* Update the RxISR function pointer */
+ hsmartcard->RxISR = SMARTCARD_RxISR;
+
+ /* Enable the UART Data Register Not Empty interrupt */
+ SET_BIT(hsmartcard->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);
+ }
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_SMARTCARD_SEND_REQ(hsmartcard, SMARTCARD_RXDATA_FLUSH_REQUEST);
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_smartcard_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_smartcard_ex.c
new file mode 100644
index 0000000000..3262fd6da0
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_smartcard_ex.c
@@ -0,0 +1,494 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_smartcard_ex.c
+ * @author MCD Application Team
+ * @brief SMARTCARD HAL module driver.
+ * This file provides extended firmware functions to manage the following
+ * functionalities of the SmartCard.
+ * + Initialization and de-initialization functions
+ * + Peripheral Control functions
+ *
+ @verbatim
+ =============================================================================
+ ##### SMARTCARD peripheral extended features #####
+ =============================================================================
+ [..]
+ The Extended SMARTCARD HAL driver can be used as follows:
+
+ (#) After having configured the SMARTCARD basic features with HAL_SMARTCARD_Init(),
+ then program SMARTCARD advanced features if required (TX/RX pins swap, TimeOut,
+ auto-retry counter,...) in the hsmartcard AdvancedInit structure.
+
+ (#) FIFO mode enabling/disabling and RX/TX FIFO threshold programming.
+
+ -@- When SMARTCARD operates in FIFO mode, FIFO mode must be enabled prior
+ starting RX/TX transfers. Also RX/TX FIFO thresholds must be
+ configured prior starting RX/TX transfers.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SMARTCARDEx SMARTCARDEx
+ * @brief SMARTCARD Extended HAL module driver
+ * @{
+ */
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup SMARTCARDEx_Private_Constants SMARTCARD Extended Private Constants
+ * @{
+ */
+/* UART RX FIFO depth */
+#define RX_FIFO_DEPTH 8U
+
+/* UART TX FIFO depth */
+#define TX_FIFO_DEPTH 8U
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void SMARTCARDEx_SetNbDataToProcess(SMARTCARD_HandleTypeDef *hsmartcard);
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup SMARTCARDEx_Exported_Functions SMARTCARD Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup SMARTCARDEx_Exported_Functions_Group1 Extended Peripheral Control functions
+ * @brief Extended control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to initialize the SMARTCARD.
+ (+) HAL_SMARTCARDEx_BlockLength_Config() API allows to configure the Block Length on the fly
+ (+) HAL_SMARTCARDEx_TimeOut_Config() API allows to configure the receiver timeout value on the fly
+ (+) HAL_SMARTCARDEx_EnableReceiverTimeOut() API enables the receiver timeout feature
+ (+) HAL_SMARTCARDEx_DisableReceiverTimeOut() API disables the receiver timeout feature
+
+@endverbatim
+ * @{
+ */
+
+/** @brief Update on the fly the SMARTCARD block length in RTOR register.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @param BlockLength SMARTCARD block length (8-bit long at most)
+ * @retval None
+ */
+void HAL_SMARTCARDEx_BlockLength_Config(SMARTCARD_HandleTypeDef *hsmartcard, uint8_t BlockLength)
+{
+ MODIFY_REG(hsmartcard->Instance->RTOR, USART_RTOR_BLEN, ((uint32_t)BlockLength << USART_RTOR_BLEN_Pos));
+}
+
+/** @brief Update on the fly the receiver timeout value in RTOR register.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @param TimeOutValue receiver timeout value in number of baud blocks. The timeout
+ * value must be less or equal to 0x0FFFFFFFF.
+ * @retval None
+ */
+void HAL_SMARTCARDEx_TimeOut_Config(SMARTCARD_HandleTypeDef *hsmartcard, uint32_t TimeOutValue)
+{
+ assert_param(IS_SMARTCARD_TIMEOUT_VALUE(hsmartcard->Init.TimeOutValue));
+ MODIFY_REG(hsmartcard->Instance->RTOR, USART_RTOR_RTO, TimeOutValue);
+}
+
+/** @brief Enable the SMARTCARD receiver timeout feature.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARDEx_EnableReceiverTimeOut(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY;
+
+ /* Set the USART RTOEN bit */
+ SET_BIT(hsmartcard->Instance->CR2, USART_CR2_RTOEN);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/** @brief Disable the SMARTCARD receiver timeout feature.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARDEx_DisableReceiverTimeOut(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ if (hsmartcard->gState == HAL_SMARTCARD_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY;
+
+ /* Clear the USART RTOEN bit */
+ CLEAR_BIT(hsmartcard->Instance->CR2, USART_CR2_RTOEN);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SMARTCARDEx_Exported_Functions_Group2 Extended Peripheral IO operation functions
+ * @brief SMARTCARD Transmit and Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of FIFO mode related callback functions.
+
+ (#) TX/RX Fifos Callbacks:
+ (++) HAL_SMARTCARDEx_RxFifoFullCallback()
+ (++) HAL_SMARTCARDEx_TxFifoEmptyCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief SMARTCARD RX Fifo full callback.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARDEx_RxFifoFullCallback(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARDEx_RxFifoFullCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief SMARTCARD TX Fifo empty callback.
+ * @param hsmartcard Pointer to a SMARTCARD_HandleTypeDef structure that contains
+ * the configuration information for the specified SMARTCARD module.
+ * @retval None
+ */
+__weak void HAL_SMARTCARDEx_TxFifoEmptyCallback(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmartcard);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMARTCARDEx_TxFifoEmptyCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SMARTCARDEx_Exported_Functions_Group3 Extended Peripheral FIFO Control functions
+ * @brief SMARTCARD control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral FIFO Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the SMARTCARD
+ FIFO feature.
+ (+) HAL_SMARTCARDEx_EnableFifoMode() API enables the FIFO mode
+ (+) HAL_SMARTCARDEx_DisableFifoMode() API disables the FIFO mode
+ (+) HAL_SMARTCARDEx_SetTxFifoThreshold() API sets the TX FIFO threshold
+ (+) HAL_SMARTCARDEx_SetRxFifoThreshold() API sets the RX FIFO threshold
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable the FIFO mode.
+ * @param hsmartcard SMARTCARD handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARDEx_EnableFifoMode(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(hsmartcard->Instance));
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY;
+
+ /* Save actual SMARTCARD configuration */
+ tmpcr1 = READ_REG(hsmartcard->Instance->CR1);
+
+ /* Disable SMARTCARD */
+ __HAL_SMARTCARD_DISABLE(hsmartcard);
+
+ /* Enable FIFO mode */
+ SET_BIT(tmpcr1, USART_CR1_FIFOEN);
+ hsmartcard->FifoMode = SMARTCARD_FIFOMODE_ENABLE;
+
+ /* Restore SMARTCARD configuration */
+ WRITE_REG(hsmartcard->Instance->CR1, tmpcr1);
+
+ /* Determine the number of data to process during RX/TX ISR execution */
+ SMARTCARDEx_SetNbDataToProcess(hsmartcard);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the FIFO mode.
+ * @param hsmartcard SMARTCARD handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARDEx_DisableFifoMode(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(hsmartcard->Instance));
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY;
+
+ /* Save actual SMARTCARD configuration */
+ tmpcr1 = READ_REG(hsmartcard->Instance->CR1);
+
+ /* Disable SMARTCARD */
+ __HAL_SMARTCARD_DISABLE(hsmartcard);
+
+ /* Enable FIFO mode */
+ CLEAR_BIT(tmpcr1, USART_CR1_FIFOEN);
+ hsmartcard->FifoMode = SMARTCARD_FIFOMODE_DISABLE;
+
+ /* Restore SMARTCARD configuration */
+ WRITE_REG(hsmartcard->Instance->CR1, tmpcr1);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the TXFIFO threshold.
+ * @param hsmartcard SMARTCARD handle.
+ * @param Threshold TX FIFO threshold value
+ * This parameter can be one of the following values:
+ * @arg @ref SMARTCARD_TXFIFO_THRESHOLD_1_8
+ * @arg @ref SMARTCARD_TXFIFO_THRESHOLD_1_4
+ * @arg @ref SMARTCARD_TXFIFO_THRESHOLD_1_2
+ * @arg @ref SMARTCARD_TXFIFO_THRESHOLD_3_4
+ * @arg @ref SMARTCARD_TXFIFO_THRESHOLD_7_8
+ * @arg @ref SMARTCARD_TXFIFO_THRESHOLD_8_8
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARDEx_SetTxFifoThreshold(SMARTCARD_HandleTypeDef *hsmartcard, uint32_t Threshold)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(hsmartcard->Instance));
+ assert_param(IS_SMARTCARD_TXFIFO_THRESHOLD(Threshold));
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY;
+
+ /* Save actual SMARTCARD configuration */
+ tmpcr1 = READ_REG(hsmartcard->Instance->CR1);
+
+ /* Disable SMARTCARD */
+ __HAL_SMARTCARD_DISABLE(hsmartcard);
+
+ /* Update TX threshold configuration */
+ MODIFY_REG(hsmartcard->Instance->CR3, USART_CR3_TXFTCFG, Threshold);
+
+ /* Determine the number of data to process during RX/TX ISR execution */
+ SMARTCARDEx_SetNbDataToProcess(hsmartcard);
+
+ /* Restore SMARTCARD configuration */
+ MODIFY_REG(hsmartcard->Instance->CR1, USART_CR1_UE, tmpcr1);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the RXFIFO threshold.
+ * @param hsmartcard SMARTCARD handle.
+ * @param Threshold RX FIFO threshold value
+ * This parameter can be one of the following values:
+ * @arg @ref SMARTCARD_RXFIFO_THRESHOLD_1_8
+ * @arg @ref SMARTCARD_RXFIFO_THRESHOLD_1_4
+ * @arg @ref SMARTCARD_RXFIFO_THRESHOLD_1_2
+ * @arg @ref SMARTCARD_RXFIFO_THRESHOLD_3_4
+ * @arg @ref SMARTCARD_RXFIFO_THRESHOLD_7_8
+ * @arg @ref SMARTCARD_RXFIFO_THRESHOLD_8_8
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMARTCARDEx_SetRxFifoThreshold(SMARTCARD_HandleTypeDef *hsmartcard, uint32_t Threshold)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(hsmartcard->Instance));
+ assert_param(IS_SMARTCARD_RXFIFO_THRESHOLD(Threshold));
+
+ /* Process Locked */
+ __HAL_LOCK(hsmartcard);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_BUSY;
+
+ /* Save actual SMARTCARD configuration */
+ tmpcr1 = READ_REG(hsmartcard->Instance->CR1);
+
+ /* Disable SMARTCARD */
+ __HAL_SMARTCARD_DISABLE(hsmartcard);
+
+ /* Update RX threshold configuration */
+ MODIFY_REG(hsmartcard->Instance->CR3, USART_CR3_RXFTCFG, Threshold);
+
+ /* Determine the number of data to process during RX/TX ISR execution */
+ SMARTCARDEx_SetNbDataToProcess(hsmartcard);
+
+ /* Restore SMARTCARD configuration */
+ MODIFY_REG(hsmartcard->Instance->CR1, USART_CR1_UE, tmpcr1);
+
+ hsmartcard->gState = HAL_SMARTCARD_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmartcard);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup SMARTCARDEx_Private_Functions SMARTCARD Extended Private Functions
+ * @{
+ */
+
+/**
+ * @brief Calculate the number of data to process in RX/TX ISR.
+ * @note The RX FIFO depth and the TX FIFO depth is extracted from
+ * the USART configuration registers.
+ * @param hsmartcard SMARTCARD handle.
+ * @retval None
+ */
+static void SMARTCARDEx_SetNbDataToProcess(SMARTCARD_HandleTypeDef *hsmartcard)
+{
+ uint8_t rx_fifo_depth;
+ uint8_t tx_fifo_depth;
+ uint8_t rx_fifo_threshold;
+ uint8_t tx_fifo_threshold;
+ /* 2 0U/1U added for MISRAC2012-Rule-18.1_b and MISRAC2012-Rule-18.1_d */
+ uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
+ uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};
+
+ if (hsmartcard->FifoMode == SMARTCARD_FIFOMODE_DISABLE)
+ {
+ hsmartcard->NbTxDataToProcess = 1U;
+ hsmartcard->NbRxDataToProcess = 1U;
+ }
+ else
+ {
+ rx_fifo_depth = RX_FIFO_DEPTH;
+ tx_fifo_depth = TX_FIFO_DEPTH;
+ rx_fifo_threshold = (uint8_t)(READ_BIT(hsmartcard->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos);
+ tx_fifo_threshold = (uint8_t)(READ_BIT(hsmartcard->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos);
+ hsmartcard->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) / (uint16_t)denominator[tx_fifo_threshold];
+ hsmartcard->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) / (uint16_t)denominator[rx_fifo_threshold];
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_smbus.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_smbus.c
new file mode 100644
index 0000000000..519756dc7d
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_smbus.c
@@ -0,0 +1,2673 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_smbus.c
+ * @author MCD Application Team
+ * @brief SMBUS HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the System Management Bus (SMBus) peripheral,
+ * based on I2C principles of operation :
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and Errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The SMBUS HAL driver can be used as follows:
+
+ (#) Declare a SMBUS_HandleTypeDef handle structure, for example:
+ SMBUS_HandleTypeDef hsmbus;
+
+ (#)Initialize the SMBUS low level resources by implementing the @ref HAL_SMBUS_MspInit() API:
+ (##) Enable the SMBUSx interface clock
+ (##) SMBUS pins configuration
+ (+++) Enable the clock for the SMBUS GPIOs
+ (+++) Configure SMBUS pins as alternate function open-drain
+ (##) NVIC configuration if you need to use interrupt process
+ (+++) Configure the SMBUSx interrupt priority
+ (+++) Enable the NVIC SMBUS IRQ Channel
+
+ (#) Configure the Communication Clock Timing, Bus Timeout, Own Address1, Master Addressing mode,
+ Dual Addressing mode, Own Address2, Own Address2 Mask, General call, Nostretch mode,
+ Peripheral mode and Packet Error Check mode in the hsmbus Init structure.
+
+ (#) Initialize the SMBUS registers by calling the @ref HAL_SMBUS_Init() API:
+ (++) These API's configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
+ by calling the customized @ref HAL_SMBUS_MspInit(&hsmbus) API.
+
+ (#) To check if target device is ready for communication, use the function @ref HAL_SMBUS_IsDeviceReady()
+
+ (#) For SMBUS IO operations, only one mode of operations is available within this driver
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Transmit in master/host SMBUS mode an amount of data in non-blocking mode using @ref HAL_SMBUS_Master_Transmit_IT()
+ (++) At transmission end of transfer @ref HAL_SMBUS_MasterTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_SMBUS_MasterTxCpltCallback()
+ (+) Receive in master/host SMBUS mode an amount of data in non-blocking mode using @ref HAL_SMBUS_Master_Receive_IT()
+ (++) At reception end of transfer @ref HAL_SMBUS_MasterRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_SMBUS_MasterRxCpltCallback()
+ (+) Abort a master/host SMBUS process communication with Interrupt using @ref HAL_SMBUS_Master_Abort_IT()
+ (++) The associated previous transfer callback is called at the end of abort process
+ (++) mean @ref HAL_SMBUS_MasterTxCpltCallback() in case of previous state was master transmit
+ (++) mean @ref HAL_SMBUS_MasterRxCpltCallback() in case of previous state was master receive
+ (+) Enable/disable the Address listen mode in slave/device or host/slave SMBUS mode
+ using @ref HAL_SMBUS_EnableListen_IT() @ref HAL_SMBUS_DisableListen_IT()
+ (++) When address slave/device SMBUS match, @ref HAL_SMBUS_AddrCallback() is executed and user can
+ add his own code to check the Address Match Code and the transmission direction request by master/host (Write/Read).
+ (++) At Listen mode end @ref HAL_SMBUS_ListenCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_SMBUS_ListenCpltCallback()
+ (+) Transmit in slave/device SMBUS mode an amount of data in non-blocking mode using @ref HAL_SMBUS_Slave_Transmit_IT()
+ (++) At transmission end of transfer @ref HAL_SMBUS_SlaveTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_SMBUS_SlaveTxCpltCallback()
+ (+) Receive in slave/device SMBUS mode an amount of data in non-blocking mode using @ref HAL_SMBUS_Slave_Receive_IT()
+ (++) At reception end of transfer @ref HAL_SMBUS_SlaveRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_SMBUS_SlaveRxCpltCallback()
+ (+) Enable/Disable the SMBUS alert mode using @ref HAL_SMBUS_EnableAlert_IT() @ref HAL_SMBUS_DisableAlert_IT()
+ (++) When SMBUS Alert is generated @ref HAL_SMBUS_ErrorCallback() is executed and user can
+ add his own code by customization of function pointer @ref HAL_SMBUS_ErrorCallback()
+ to check the Alert Error Code using function @ref HAL_SMBUS_GetError()
+ (+) Get HAL state machine or error values using @ref HAL_SMBUS_GetState() or @ref HAL_SMBUS_GetError()
+ (+) In case of transfer Error, @ref HAL_SMBUS_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer @ref HAL_SMBUS_ErrorCallback()
+ to check the Error Code using function @ref HAL_SMBUS_GetError()
+
+ *** SMBUS HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in SMBUS HAL driver.
+
+ (+) @ref __HAL_SMBUS_ENABLE: Enable the SMBUS peripheral
+ (+) @ref __HAL_SMBUS_DISABLE: Disable the SMBUS peripheral
+ (+) @ref __HAL_SMBUS_GET_FLAG: Check whether the specified SMBUS flag is set or not
+ (+) @ref __HAL_SMBUS_CLEAR_FLAG: Clear the specified SMBUS pending flag
+ (+) @ref __HAL_SMBUS_ENABLE_IT: Enable the specified SMBUS interrupt
+ (+) @ref __HAL_SMBUS_DISABLE_IT: Disable the specified SMBUS interrupt
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation flag USE_HAL_SMBUS_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions @ref HAL_SMBUS_RegisterCallback() or @ref HAL_SMBUS_RegisterAddrCallback()
+ to register an interrupt callback.
+ [..]
+ Function @ref HAL_SMBUS_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.
+ (+) ErrorCallback : callback for error detection.
+ (+) 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 : @ref HAL_SMBUS_RegisterAddrCallback.
+ [..]
+ Use function @ref HAL_SMBUS_UnRegisterCallback to reset a callback to the default
+ weak function.
+ @ref HAL_SMBUS_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.
+ (+) ErrorCallback : callback for error detection.
+ (+) MspInitCallback : callback for Msp Init.
+ (+) MspDeInitCallback : callback for Msp DeInit.
+ [..]
+ For callback AddrCallback use dedicated register callbacks : @ref HAL_SMBUS_UnRegisterAddrCallback.
+ [..]
+ By default, after the @ref HAL_SMBUS_Init() and when the state is @ref HAL_I2C_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples @ref HAL_SMBUS_MasterTxCpltCallback(), @ref HAL_SMBUS_MasterRxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the @ref HAL_SMBUS_Init()/ @ref HAL_SMBUS_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ If MspInit or MspDeInit are not null, the @ref HAL_SMBUS_Init()/ @ref HAL_SMBUS_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+ [..]
+ Callbacks can be registered/unregistered in @ref HAL_I2C_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in @ref HAL_I2C_STATE_READY or @ref 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 @ref HAL_SMBUS_RegisterCallback() before calling @ref HAL_SMBUS_DeInit()
+ or @ref HAL_SMBUS_Init() function.
+ [..]
+ When the compilation flag USE_HAL_SMBUS_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 SMBUS HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SMBUS SMBUS
+ * @brief SMBUS HAL module driver
+ * @{
+ */
+
+#ifdef HAL_SMBUS_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @defgroup SMBUS_Private_Define SMBUS Private Constants
+ * @{
+ */
+#define TIMING_CLEAR_MASK (0xF0FFFFFFUL) /*!< SMBUS TIMING clear register Mask */
+#define HAL_TIMEOUT_ADDR (10000U) /*!< 10 s */
+#define HAL_TIMEOUT_BUSY (25U) /*!< 25 ms */
+#define HAL_TIMEOUT_DIR (25U) /*!< 25 ms */
+#define HAL_TIMEOUT_RXNE (25U) /*!< 25 ms */
+#define HAL_TIMEOUT_STOPF (25U) /*!< 25 ms */
+#define HAL_TIMEOUT_TC (25U) /*!< 25 ms */
+#define HAL_TIMEOUT_TCR (25U) /*!< 25 ms */
+#define HAL_TIMEOUT_TXIS (25U) /*!< 25 ms */
+#define MAX_NBYTE_SIZE 255U
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup SMBUS_Private_Functions SMBUS Private Functions
+ * @{
+ */
+static HAL_StatusTypeDef SMBUS_WaitOnFlagUntilTimeout(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t Flag, FlagStatus Status, uint32_t Timeout);
+
+static void SMBUS_Enable_IRQ(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest);
+static void SMBUS_Disable_IRQ(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest);
+static HAL_StatusTypeDef SMBUS_Master_ISR(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags);
+static HAL_StatusTypeDef SMBUS_Slave_ISR(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags);
+
+static void SMBUS_ConvertOtherXferOptions(struct __SMBUS_HandleTypeDef *hsmbus);
+
+static void SMBUS_ITErrorHandler(struct __SMBUS_HandleTypeDef *hsmbus);
+
+static void SMBUS_TransferConfig(struct __SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup SMBUS_Exported_Functions SMBUS Exported Functions
+ * @{
+ */
+
+/** @defgroup SMBUS_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 SMBUSx peripheral:
+
+ (+) User must Implement HAL_SMBUS_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, IT and NVIC ).
+
+ (+) Call the function HAL_SMBUS_Init() to configure the selected device with
+ the selected configuration:
+ (++) Clock Timing
+ (++) Bus Timeout
+ (++) Analog Filer mode
+ (++) Own Address 1
+ (++) Addressing mode (Master, Slave)
+ (++) Dual Addressing mode
+ (++) Own Address 2
+ (++) Own Address 2 Mask
+ (++) General call mode
+ (++) Nostretch mode
+ (++) Packet Error Check mode
+ (++) Peripheral mode
+
+
+ (+) Call the function HAL_SMBUS_DeInit() to restore the default configuration
+ of the selected SMBUSx peripheral.
+
+ (+) Enable/Disable Analog/Digital filters with HAL_SMBUS_ConfigAnalogFilter() and
+ HAL_SMBUS_ConfigDigitalFilter().
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the SMBUS according to the specified parameters
+ * in the SMBUS_InitTypeDef and initialize the associated handle.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_Init(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Check the SMBUS handle allocation */
+ if (hsmbus == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
+ assert_param(IS_SMBUS_ANALOG_FILTER(hsmbus->Init.AnalogFilter));
+ assert_param(IS_SMBUS_OWN_ADDRESS1(hsmbus->Init.OwnAddress1));
+ assert_param(IS_SMBUS_ADDRESSING_MODE(hsmbus->Init.AddressingMode));
+ assert_param(IS_SMBUS_DUAL_ADDRESS(hsmbus->Init.DualAddressMode));
+ assert_param(IS_SMBUS_OWN_ADDRESS2(hsmbus->Init.OwnAddress2));
+ assert_param(IS_SMBUS_OWN_ADDRESS2_MASK(hsmbus->Init.OwnAddress2Masks));
+ assert_param(IS_SMBUS_GENERAL_CALL(hsmbus->Init.GeneralCallMode));
+ assert_param(IS_SMBUS_NO_STRETCH(hsmbus->Init.NoStretchMode));
+ assert_param(IS_SMBUS_PEC(hsmbus->Init.PacketErrorCheckMode));
+ assert_param(IS_SMBUS_PERIPHERAL_MODE(hsmbus->Init.PeripheralMode));
+
+ if (hsmbus->State == HAL_SMBUS_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hsmbus->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->MasterTxCpltCallback = HAL_SMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
+ hsmbus->MasterRxCpltCallback = HAL_SMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
+ hsmbus->SlaveTxCpltCallback = HAL_SMBUS_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */
+ hsmbus->SlaveRxCpltCallback = HAL_SMBUS_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */
+ hsmbus->ListenCpltCallback = HAL_SMBUS_ListenCpltCallback; /* Legacy weak ListenCpltCallback */
+ hsmbus->ErrorCallback = HAL_SMBUS_ErrorCallback; /* Legacy weak ErrorCallback */
+ hsmbus->AddrCallback = HAL_SMBUS_AddrCallback; /* Legacy weak AddrCallback */
+
+ if (hsmbus->MspInitCallback == NULL)
+ {
+ hsmbus->MspInitCallback = HAL_SMBUS_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ hsmbus->MspInitCallback(hsmbus);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ HAL_SMBUS_MspInit(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+
+ hsmbus->State = HAL_SMBUS_STATE_BUSY;
+
+ /* Disable the selected SMBUS peripheral */
+ __HAL_SMBUS_DISABLE(hsmbus);
+
+ /*---------------------------- SMBUSx TIMINGR Configuration ------------------------*/
+ /* Configure SMBUSx: Frequency range */
+ hsmbus->Instance->TIMINGR = hsmbus->Init.Timing & TIMING_CLEAR_MASK;
+
+ /*---------------------------- SMBUSx TIMEOUTR Configuration ------------------------*/
+ /* Configure SMBUSx: Bus Timeout */
+ hsmbus->Instance->TIMEOUTR &= ~I2C_TIMEOUTR_TIMOUTEN;
+ hsmbus->Instance->TIMEOUTR &= ~I2C_TIMEOUTR_TEXTEN;
+ hsmbus->Instance->TIMEOUTR = hsmbus->Init.SMBusTimeout;
+
+ /*---------------------------- SMBUSx OAR1 Configuration -----------------------*/
+ /* Configure SMBUSx: Own Address1 and ack own address1 mode */
+ hsmbus->Instance->OAR1 &= ~I2C_OAR1_OA1EN;
+
+ if (hsmbus->Init.OwnAddress1 != 0UL)
+ {
+ if (hsmbus->Init.AddressingMode == SMBUS_ADDRESSINGMODE_7BIT)
+ {
+ hsmbus->Instance->OAR1 = (I2C_OAR1_OA1EN | hsmbus->Init.OwnAddress1);
+ }
+ else /* SMBUS_ADDRESSINGMODE_10BIT */
+ {
+ hsmbus->Instance->OAR1 = (I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | hsmbus->Init.OwnAddress1);
+ }
+ }
+
+ /*---------------------------- SMBUSx CR2 Configuration ------------------------*/
+ /* Configure SMBUSx: Addressing Master mode */
+ if (hsmbus->Init.AddressingMode == SMBUS_ADDRESSINGMODE_10BIT)
+ {
+ hsmbus->Instance->CR2 = (I2C_CR2_ADD10);
+ }
+ /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process) */
+ /* AUTOEND and NACK bit will be manage during Transfer process */
+ hsmbus->Instance->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK);
+
+ /*---------------------------- SMBUSx OAR2 Configuration -----------------------*/
+ /* Configure SMBUSx: Dual mode and Own Address2 */
+ hsmbus->Instance->OAR2 = (hsmbus->Init.DualAddressMode | hsmbus->Init.OwnAddress2 | (hsmbus->Init.OwnAddress2Masks << 8U));
+
+ /*---------------------------- SMBUSx CR1 Configuration ------------------------*/
+ /* Configure SMBUSx: Generalcall and NoStretch mode */
+ hsmbus->Instance->CR1 = (hsmbus->Init.GeneralCallMode | hsmbus->Init.NoStretchMode | hsmbus->Init.PacketErrorCheckMode | hsmbus->Init.PeripheralMode | hsmbus->Init.AnalogFilter);
+
+ /* Enable Slave Byte Control only in case of Packet Error Check is enabled and SMBUS Peripheral is set in Slave mode */
+ if ((hsmbus->Init.PacketErrorCheckMode == SMBUS_PEC_ENABLE)
+ && ((hsmbus->Init.PeripheralMode == SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE) || (hsmbus->Init.PeripheralMode == SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE_ARP)))
+ {
+ hsmbus->Instance->CR1 |= I2C_CR1_SBC;
+ }
+
+ /* Enable the selected SMBUS peripheral */
+ __HAL_SMBUS_ENABLE(hsmbus);
+
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
+ hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the SMBUS peripheral.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_DeInit(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Check the SMBUS handle allocation */
+ if (hsmbus == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
+
+ hsmbus->State = HAL_SMBUS_STATE_BUSY;
+
+ /* Disable the SMBUS Peripheral Clock */
+ __HAL_SMBUS_DISABLE(hsmbus);
+
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ if (hsmbus->MspDeInitCallback == NULL)
+ {
+ hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ hsmbus->MspDeInitCallback(hsmbus);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_SMBUS_MspDeInit(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
+ hsmbus->PreviousState = HAL_SMBUS_STATE_RESET;
+ hsmbus->State = HAL_SMBUS_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsmbus);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the SMBUS MSP.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+__weak void HAL_SMBUS_MspInit(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmbus);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMBUS_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the SMBUS MSP.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+__weak void HAL_SMBUS_MspDeInit(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmbus);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMBUS_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Configure Analog noise filter.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param AnalogFilter This parameter can be one of the following values:
+ * @arg @ref SMBUS_ANALOGFILTER_ENABLE
+ * @arg @ref SMBUS_ANALOGFILTER_DISABLE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_ConfigAnalogFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t AnalogFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
+ assert_param(IS_SMBUS_ANALOG_FILTER(AnalogFilter));
+
+ if (hsmbus->State == HAL_SMBUS_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ hsmbus->State = HAL_SMBUS_STATE_BUSY;
+
+ /* Disable the selected SMBUS peripheral */
+ __HAL_SMBUS_DISABLE(hsmbus);
+
+ /* Reset ANOFF bit */
+ hsmbus->Instance->CR1 &= ~(I2C_CR1_ANFOFF);
+
+ /* Set analog filter bit*/
+ hsmbus->Instance->CR1 |= AnalogFilter;
+
+ __HAL_SMBUS_ENABLE(hsmbus);
+
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Configure Digital noise filter.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_ConfigDigitalFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t DigitalFilter)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
+ assert_param(IS_SMBUS_DIGITAL_FILTER(DigitalFilter));
+
+ if (hsmbus->State == HAL_SMBUS_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ hsmbus->State = HAL_SMBUS_STATE_BUSY;
+
+ /* Disable the selected SMBUS peripheral */
+ __HAL_SMBUS_DISABLE(hsmbus);
+
+ /* Get the old register value */
+ tmpreg = hsmbus->Instance->CR1;
+
+ /* Reset I2C DNF bits [11:8] */
+ tmpreg &= ~(I2C_CR1_DNF);
+
+ /* Set I2Cx DNF coefficient */
+ tmpreg |= DigitalFilter << I2C_CR1_DNF_Pos;
+
+ /* Store the new register value */
+ hsmbus->Instance->CR1 = tmpreg;
+
+ __HAL_SMBUS_ENABLE(hsmbus);
+
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User SMBUS Callback
+ * To be used instead of the weak predefined callback
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
+ * @arg @ref HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
+ * @arg @ref HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
+ * @arg @ref HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
+ * @arg @ref HAL_SMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
+ * @arg @ref HAL_SMBUS_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_SMBUS_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_SMBUS_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_RegisterCallback(SMBUS_HandleTypeDef *hsmbus, HAL_SMBUS_CallbackIDTypeDef CallbackID, pSMBUS_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hsmbus);
+
+ if (HAL_SMBUS_STATE_READY == hsmbus->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID :
+ hsmbus->MasterTxCpltCallback = pCallback;
+ break;
+
+ case HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID :
+ hsmbus->MasterRxCpltCallback = pCallback;
+ break;
+
+ case HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID :
+ hsmbus->SlaveTxCpltCallback = pCallback;
+ break;
+
+ case HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID :
+ hsmbus->SlaveRxCpltCallback = pCallback;
+ break;
+
+ case HAL_SMBUS_LISTEN_COMPLETE_CB_ID :
+ hsmbus->ListenCpltCallback = pCallback;
+ break;
+
+ case HAL_SMBUS_ERROR_CB_ID :
+ hsmbus->ErrorCallback = pCallback;
+ break;
+
+ case HAL_SMBUS_MSPINIT_CB_ID :
+ hsmbus->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SMBUS_MSPDEINIT_CB_ID :
+ hsmbus->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_SMBUS_STATE_RESET == hsmbus->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SMBUS_MSPINIT_CB_ID :
+ hsmbus->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SMBUS_MSPDEINIT_CB_ID :
+ hsmbus->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsmbus);
+ return status;
+}
+
+/**
+ * @brief Unregister an SMBUS Callback
+ * SMBUS callback is redirected to the weak predefined callback
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @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_SMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
+ * @arg @ref HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
+ * @arg @ref HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
+ * @arg @ref HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
+ * @arg @ref HAL_SMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
+ * @arg @ref HAL_SMBUS_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_SMBUS_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_SMBUS_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_UnRegisterCallback(SMBUS_HandleTypeDef *hsmbus, HAL_SMBUS_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hsmbus);
+
+ if (HAL_SMBUS_STATE_READY == hsmbus->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID :
+ hsmbus->MasterTxCpltCallback = HAL_SMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
+ break;
+
+ case HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID :
+ hsmbus->MasterRxCpltCallback = HAL_SMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
+ break;
+
+ case HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID :
+ hsmbus->SlaveTxCpltCallback = HAL_SMBUS_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */
+ break;
+
+ case HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID :
+ hsmbus->SlaveRxCpltCallback = HAL_SMBUS_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */
+ break;
+
+ case HAL_SMBUS_LISTEN_COMPLETE_CB_ID :
+ hsmbus->ListenCpltCallback = HAL_SMBUS_ListenCpltCallback; /* Legacy weak ListenCpltCallback */
+ break;
+
+ case HAL_SMBUS_ERROR_CB_ID :
+ hsmbus->ErrorCallback = HAL_SMBUS_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_SMBUS_MSPINIT_CB_ID :
+ hsmbus->MspInitCallback = HAL_SMBUS_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_SMBUS_MSPDEINIT_CB_ID :
+ hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_SMBUS_STATE_RESET == hsmbus->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SMBUS_MSPINIT_CB_ID :
+ hsmbus->MspInitCallback = HAL_SMBUS_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_SMBUS_MSPDEINIT_CB_ID :
+ hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsmbus);
+ return status;
+}
+
+/**
+ * @brief Register the Slave Address Match SMBUS Callback
+ * To be used instead of the weak HAL_SMBUS_AddrCallback() predefined callback
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param pCallback pointer to the Address Match Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_RegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus, pSMBUS_AddrCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hsmbus);
+
+ if (HAL_SMBUS_STATE_READY == hsmbus->State)
+ {
+ hsmbus->AddrCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsmbus);
+ return status;
+}
+
+/**
+ * @brief UnRegister the Slave Address Match SMBUS Callback
+ * Info Ready SMBUS Callback is redirected to the weak HAL_SMBUS_AddrCallback() predefined callback
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_UnRegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hsmbus);
+
+ if (HAL_SMBUS_STATE_READY == hsmbus->State)
+ {
+ hsmbus->AddrCallback = HAL_SMBUS_AddrCallback; /* Legacy weak AddrCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsmbus);
+ return status;
+}
+
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup SMBUS_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 SMBUS data
+ transfers.
+
+ (#) Blocking mode function to check if device is ready for usage is :
+ (++) HAL_SMBUS_IsDeviceReady()
+
+ (#) There is only one mode of transfer:
+ (++) Non-Blocking mode : The communication is performed using Interrupts.
+ These functions return the status of the transfer startup.
+ The end of the data processing will be indicated through the
+ dedicated SMBUS IRQ when using Interrupt mode.
+
+ (#) Non-Blocking mode functions with Interrupt are :
+ (++) HAL_SMBUS_Master_Transmit_IT()
+ (++) HAL_SMBUS_Master_Receive_IT()
+ (++) HAL_SMBUS_Slave_Transmit_IT()
+ (++) HAL_SMBUS_Slave_Receive_IT()
+ (++) HAL_SMBUS_EnableListen_IT() or alias HAL_SMBUS_EnableListen_IT()
+ (++) HAL_SMBUS_DisableListen_IT()
+ (++) HAL_SMBUS_EnableAlert_IT()
+ (++) HAL_SMBUS_DisableAlert_IT()
+
+ (#) A set of Transfer Complete Callbacks are provided in non-Blocking mode:
+ (++) HAL_SMBUS_MasterTxCpltCallback()
+ (++) HAL_SMBUS_MasterRxCpltCallback()
+ (++) HAL_SMBUS_SlaveTxCpltCallback()
+ (++) HAL_SMBUS_SlaveRxCpltCallback()
+ (++) HAL_SMBUS_AddrCallback()
+ (++) HAL_SMBUS_ListenCpltCallback()
+ (++) HAL_SMBUS_ErrorCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmit in master/host SMBUS mode an amount of data in non-blocking mode with Interrupt.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @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 SMBUS_XferOptions_definition
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_Master_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hsmbus->State == HAL_SMBUS_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_TX;
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
+ /* Prepare transfer parameters */
+ hsmbus->pBuffPtr = pData;
+ hsmbus->XferCount = Size;
+ hsmbus->XferOptions = XferOptions;
+
+ /* In case of Quick command, remove autoend mode */
+ /* Manage the stop generation by software */
+ if (hsmbus->pBuffPtr == NULL)
+ {
+ hsmbus->XferOptions &= ~SMBUS_AUTOEND_MODE;
+ }
+
+ if (Size > MAX_NBYTE_SIZE)
+ {
+ hsmbus->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hsmbus->XferSize = Size;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */
+ if ((hsmbus->XferSize < hsmbus->XferCount) && (hsmbus->XferSize == MAX_NBYTE_SIZE))
+ {
+ SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE), SMBUS_GENERATE_START_WRITE);
+ }
+ else
+ {
+ /* If transfer direction not change, do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+
+ /* Store current volatile XferOptions, misra rule */
+ tmp = hsmbus->XferOptions;
+
+ if ((hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_TX) && (IS_SMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(tmp) == 0))
+ {
+ SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions, SMBUS_NO_STARTSTOP);
+ }
+ /* Else transfer direction change, so generate Restart with new transfer direction */
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ SMBUS_ConvertOtherXferOptions(hsmbus);
+
+ /* Handle Transfer */
+ SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions, SMBUS_GENERATE_START_WRITE);
+ }
+
+ /* If PEC mode is enable, size to transmit manage by SW part should be Size-1 byte, corresponding to PEC byte */
+ /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
+ if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
+ {
+ hsmbus->XferSize--;
+ hsmbus->XferCount--;
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Note : The SMBUS interrupts must be enabled after unlocking current process
+ to avoid the risk of SMBUS interrupt handle execution before current
+ process unlock */
+ SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_TX);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in master/host SMBUS mode an amount of data in non-blocking mode with Interrupt.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @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 SMBUS_XferOptions_definition
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_Master_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hsmbus->State == HAL_SMBUS_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_RX;
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hsmbus->pBuffPtr = pData;
+ hsmbus->XferCount = Size;
+ hsmbus->XferOptions = XferOptions;
+
+ /* In case of Quick command, remove autoend mode */
+ /* Manage the stop generation by software */
+ if (hsmbus->pBuffPtr == NULL)
+ {
+ hsmbus->XferOptions &= ~SMBUS_AUTOEND_MODE;
+ }
+
+ if (Size > MAX_NBYTE_SIZE)
+ {
+ hsmbus->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hsmbus->XferSize = Size;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */
+ if ((hsmbus->XferSize < hsmbus->XferCount) && (hsmbus->XferSize == MAX_NBYTE_SIZE))
+ {
+ SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE), SMBUS_GENERATE_START_READ);
+ }
+ else
+ {
+ /* If transfer direction not change, do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+
+ /* Store current volatile XferOptions, Misra rule */
+ tmp = hsmbus->XferOptions;
+
+ if ((hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_RX) && (IS_SMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(tmp) == 0))
+ {
+ SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions, SMBUS_NO_STARTSTOP);
+ }
+ /* Else transfer direction change, so generate Restart with new transfer direction */
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ SMBUS_ConvertOtherXferOptions(hsmbus);
+
+ /* Handle Transfer */
+ SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions, SMBUS_GENERATE_START_READ);
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Note : The SMBUS interrupts must be enabled after unlocking current process
+ to avoid the risk of SMBUS interrupt handle execution before current
+ process unlock */
+ SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_RX);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Abort a master/host SMBUS process communication with Interrupt.
+ * @note This abort can be called only if state is ready
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @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_SMBUS_Master_Abort_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress)
+{
+ if (hsmbus->State == HAL_SMBUS_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ /* Keep the same state as previous */
+ /* to perform as well the call of the corresponding end of transfer callback */
+ if (hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_TX)
+ {
+ hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_TX;
+ }
+ else if (hsmbus->PreviousState == HAL_SMBUS_STATE_MASTER_BUSY_RX)
+ {
+ hsmbus->State = HAL_SMBUS_STATE_MASTER_BUSY_RX;
+ }
+ else
+ {
+ /* Wrong usage of abort function */
+ /* This function should be used only in case of abort monitored by master device */
+ return HAL_ERROR;
+ }
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
+
+ /* Set NBYTES to 1 to generate a dummy read on SMBUS peripheral */
+ /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */
+ SMBUS_TransferConfig(hsmbus, DevAddress, 1, SMBUS_AUTOEND_MODE, SMBUS_NO_STARTSTOP);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Note : The SMBUS interrupts must be enabled after unlocking current process
+ to avoid the risk of SMBUS interrupt handle execution before current
+ process unlock */
+ if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
+ {
+ SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_TX);
+ }
+ else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
+ {
+ SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_RX);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in slave/device SMBUS mode an amount of data in non-blocking mode with Interrupt.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_Slave_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
+{
+ /* Check the parameters */
+ assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR | SMBUS_IT_TX);
+
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ hsmbus->State = (HAL_SMBUS_STATE_SLAVE_BUSY_TX | HAL_SMBUS_STATE_LISTEN);
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
+
+ /* Set SBC bit to manage Acknowledge at each bit */
+ hsmbus->Instance->CR1 |= I2C_CR1_SBC;
+
+ /* Enable Address Acknowledge */
+ hsmbus->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hsmbus->pBuffPtr = pData;
+ hsmbus->XferCount = Size;
+ hsmbus->XferOptions = XferOptions;
+
+ /* Convert OTHER_xxx XferOptions if any */
+ SMBUS_ConvertOtherXferOptions(hsmbus);
+
+ if (Size > MAX_NBYTE_SIZE)
+ {
+ hsmbus->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hsmbus->XferSize = Size;
+ }
+
+ /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */
+ if ((hsmbus->XferSize < hsmbus->XferCount) && (hsmbus->XferSize == MAX_NBYTE_SIZE))
+ {
+ SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE), SMBUS_NO_STARTSTOP);
+ }
+ else
+ {
+ /* Set NBYTE to transmit */
+ SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions, SMBUS_NO_STARTSTOP);
+
+ /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */
+ /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
+ if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
+ {
+ hsmbus->XferSize--;
+ hsmbus->XferCount--;
+ }
+ }
+
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the HOST */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ADDR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Note : The SMBUS interrupts must be enabled after unlocking current process
+ to avoid the risk of SMBUS interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_TX | SMBUS_IT_ADDR);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave/device SMBUS mode an amount of data in non-blocking mode with Interrupt.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_Slave_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
+{
+ /* Check the parameters */
+ assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR | SMBUS_IT_RX);
+
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ hsmbus->State = (HAL_SMBUS_STATE_SLAVE_BUSY_RX | HAL_SMBUS_STATE_LISTEN);
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
+
+ /* Set SBC bit to manage Acknowledge at each bit */
+ hsmbus->Instance->CR1 |= I2C_CR1_SBC;
+
+ /* Enable Address Acknowledge */
+ hsmbus->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hsmbus->pBuffPtr = pData;
+ hsmbus->XferSize = Size;
+ hsmbus->XferCount = Size;
+ hsmbus->XferOptions = XferOptions;
+
+ /* Convert OTHER_xxx XferOptions if any */
+ SMBUS_ConvertOtherXferOptions(hsmbus);
+
+ /* Set NBYTE to receive */
+ /* If XferSize equal "1", or XferSize equal "2" with PEC requested (mean 1 data byte + 1 PEC byte */
+ /* no need to set RELOAD bit mode, a ACK will be automatically generated in that case */
+ /* else need to set RELOAD bit mode to generate an automatic ACK at each byte Received */
+ /* This RELOAD bit will be reset for last BYTE to be receive in SMBUS_Slave_ISR */
+ if (((SMBUS_GET_PEC_MODE(hsmbus) != 0UL) && (hsmbus->XferSize == 2U)) || (hsmbus->XferSize == 1U))
+ {
+ SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions, SMBUS_NO_STARTSTOP);
+ }
+ else
+ {
+ SMBUS_TransferConfig(hsmbus, 0, 1, hsmbus->XferOptions | SMBUS_RELOAD_MODE, SMBUS_NO_STARTSTOP);
+ }
+
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the HOST */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ADDR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Note : The SMBUS interrupts must be enabled after unlocking current process
+ to avoid the risk of SMBUS interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_RX | SMBUS_IT_ADDR);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Enable the Address listen mode with Interrupt.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_EnableListen_IT(SMBUS_HandleTypeDef *hsmbus)
+{
+ hsmbus->State = HAL_SMBUS_STATE_LISTEN;
+
+ /* Enable the Address Match interrupt */
+ SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_ADDR);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the Address listen mode with Interrupt.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_DisableListen_IT(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Disable Address listen mode only if a transfer is not ongoing */
+ if (hsmbus->State == HAL_SMBUS_STATE_LISTEN)
+ {
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Disable the Address Match interrupt */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Enable the SMBUS alert mode with Interrupt.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUSx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_EnableAlert_IT(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Enable SMBus alert */
+ hsmbus->Instance->CR1 |= I2C_CR1_ALERTEN;
+
+ /* Clear ALERT flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ALERT);
+
+ /* Enable Alert Interrupt */
+ SMBUS_Enable_IRQ(hsmbus, SMBUS_IT_ALERT);
+
+ return HAL_OK;
+}
+/**
+ * @brief Disable the SMBUS alert mode with Interrupt.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUSx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SMBUS_DisableAlert_IT(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Enable SMBus alert */
+ hsmbus->Instance->CR1 &= ~I2C_CR1_ALERTEN;
+
+ /* Disable Alert Interrupt */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ALERT);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Check if target device is ready for communication.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @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_SMBUS_IsDeviceReady(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ __IO uint32_t SMBUS_Trials = 0UL;
+
+ FlagStatus tmp1;
+ FlagStatus tmp2;
+
+ if (hsmbus->State == HAL_SMBUS_STATE_READY)
+ {
+ if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_BUSY) != RESET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ hsmbus->State = HAL_SMBUS_STATE_BUSY;
+ hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE;
+
+ do
+ {
+ /* Generate Start */
+ hsmbus->Instance->CR2 = SMBUS_GENERATE_START(hsmbus->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_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_STOPF);
+ tmp2 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF);
+
+ while ((tmp1 == RESET) && (tmp2 == RESET))
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+ {
+ /* Device is ready */
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Update SMBUS error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_HALTIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+ return HAL_ERROR;
+ }
+ }
+
+ tmp1 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_STOPF);
+ tmp2 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF);
+ }
+
+ /* Check if the NACKF flag has not been set */
+ if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF) == RESET)
+ {
+ /* Wait until STOPF flag is reset */
+ if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
+
+ /* Device is ready */
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Wait until STOPF flag is reset */
+ if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear NACK Flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
+
+ /* Clear STOP Flag, auto generated with autoend*/
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
+ }
+
+ /* Check if the maximum allowed number of trials has been reached */
+ if (SMBUS_Trials == Trials)
+ {
+ /* Generate Stop */
+ hsmbus->Instance->CR2 |= I2C_CR2_STOP;
+
+ /* Wait until STOPF flag is reset */
+ if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
+ }
+
+ /* Increment Trials */
+ SMBUS_Trials++;
+ }
+ while (SMBUS_Trials < Trials);
+
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Update SMBUS error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_HALTIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @}
+ */
+
+/** @defgroup SMBUS_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks
+ * @{
+ */
+
+/**
+ * @brief Handle SMBUS event interrupt request.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+void HAL_SMBUS_EV_IRQHandler(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Use a local variable to store the current ISR flags */
+ /* This action will avoid a wrong treatment due to ISR flags change during interrupt handler */
+ uint32_t tmpisrvalue = READ_REG(hsmbus->Instance->ISR);
+ uint32_t tmpcr1value = READ_REG(hsmbus->Instance->CR1);
+
+ /* SMBUS in mode Transmitter ---------------------------------------------------*/
+ if ((SMBUS_CHECK_IT_SOURCE(tmpcr1value, (SMBUS_IT_TCI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_TXI)) != RESET) && ((SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TXIS) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TCR) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TC) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_STOPF) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_AF) != RESET)))
+ {
+ /* Slave mode selected */
+ if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_TX) == HAL_SMBUS_STATE_SLAVE_BUSY_TX)
+ {
+ (void)SMBUS_Slave_ISR(hsmbus, tmpisrvalue);
+ }
+ /* Master mode selected */
+ else if ((hsmbus->State & HAL_SMBUS_STATE_MASTER_BUSY_TX) == HAL_SMBUS_STATE_MASTER_BUSY_TX)
+ {
+ (void)SMBUS_Master_ISR(hsmbus, tmpisrvalue);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+
+ /* SMBUS in mode Receiver ----------------------------------------------------*/
+ if ((SMBUS_CHECK_IT_SOURCE(tmpcr1value, (SMBUS_IT_TCI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_RXI)) != RESET) && ((SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_RXNE) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TCR) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_TC) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_STOPF) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_AF) != RESET)))
+ {
+ /* Slave mode selected */
+ if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_RX) == HAL_SMBUS_STATE_SLAVE_BUSY_RX)
+ {
+ (void)SMBUS_Slave_ISR(hsmbus, tmpisrvalue);
+ }
+ /* Master mode selected */
+ else if ((hsmbus->State & HAL_SMBUS_STATE_MASTER_BUSY_RX) == HAL_SMBUS_STATE_MASTER_BUSY_RX)
+ {
+ (void)SMBUS_Master_ISR(hsmbus, tmpisrvalue);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+
+ /* SMBUS in mode Listener Only --------------------------------------------------*/
+ if (((SMBUS_CHECK_IT_SOURCE(tmpcr1value, SMBUS_IT_ADDRI) != RESET) || (SMBUS_CHECK_IT_SOURCE(tmpcr1value, SMBUS_IT_STOPI) != RESET) || (SMBUS_CHECK_IT_SOURCE(tmpcr1value, SMBUS_IT_NACKI) != RESET)) && ((SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_ADDR) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_STOPF) != RESET) || (SMBUS_CHECK_FLAG(tmpisrvalue, SMBUS_FLAG_AF) != RESET)))
+ {
+ if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
+ {
+ (void)SMBUS_Slave_ISR(hsmbus, tmpisrvalue);
+ }
+ }
+}
+
+/**
+ * @brief Handle SMBUS error interrupt request.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+void HAL_SMBUS_ER_IRQHandler(SMBUS_HandleTypeDef *hsmbus)
+{
+ SMBUS_ITErrorHandler(hsmbus);
+}
+
+/**
+ * @brief Master Tx Transfer completed callback.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+__weak void HAL_SMBUS_MasterTxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmbus);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMBUS_MasterTxCpltCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Master Rx Transfer completed callback.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+__weak void HAL_SMBUS_MasterRxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmbus);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMBUS_MasterRxCpltCallback() could be implemented in the user file
+ */
+}
+
+/** @brief Slave Tx Transfer completed callback.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+__weak void HAL_SMBUS_SlaveTxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmbus);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMBUS_SlaveTxCpltCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Slave Rx Transfer completed callback.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+__weak void HAL_SMBUS_SlaveRxCpltCallback(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmbus);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMBUS_SlaveRxCpltCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Slave Address Match callback.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param TransferDirection Master request Transfer Direction (Write/Read)
+ * @param AddrMatchCode Address Match Code
+ * @retval None
+ */
+__weak void HAL_SMBUS_AddrCallback(SMBUS_HandleTypeDef *hsmbus, uint8_t TransferDirection, uint16_t AddrMatchCode)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmbus);
+ UNUSED(TransferDirection);
+ UNUSED(AddrMatchCode);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMBUS_AddrCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Listen Complete callback.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+__weak void HAL_SMBUS_ListenCpltCallback(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmbus);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMBUS_ListenCpltCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SMBUS error callback.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval None
+ */
+__weak void HAL_SMBUS_ErrorCallback(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsmbus);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SMBUS_ErrorCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SMBUS_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief Peripheral State and Errors 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 SMBUS handle state.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @retval HAL state
+ */
+uint32_t HAL_SMBUS_GetState(SMBUS_HandleTypeDef *hsmbus)
+{
+ /* Return SMBUS handle state */
+ return hsmbus->State;
+}
+
+/**
+* @brief Return the SMBUS error code.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+* @retval SMBUS Error Code
+*/
+uint32_t HAL_SMBUS_GetError(SMBUS_HandleTypeDef *hsmbus)
+{
+ return hsmbus->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup SMBUS_Private_Functions SMBUS Private Functions
+ * @brief Data transfers Private functions
+ * @{
+ */
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param StatusFlags Value of Interrupt Flags.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SMBUS_Master_ISR(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags)
+{
+ uint16_t DevAddress;
+
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_AF) != RESET)
+ {
+ /* Clear NACK Flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ /* No need to generate STOP, it is automatically done */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ACKF;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the Error callback to inform upper layer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->ErrorCallback(hsmbus);
+#else
+ HAL_SMBUS_ErrorCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_STOPF) != RESET)
+ {
+ /* Check and treat errors if errors occurs during STOP process */
+ SMBUS_ITErrorHandler(hsmbus);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
+ {
+ /* Disable Interrupt */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
+
+ /* Clear STOP Flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ SMBUS_RESET_CR2(hsmbus);
+
+ /* Flush remaining data in Fifo register in case of error occurs before TXEmpty */
+ /* Disable the selected SMBUS peripheral */
+ __HAL_SMBUS_DISABLE(hsmbus);
+
+ hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* REenable the selected SMBUS peripheral */
+ __HAL_SMBUS_ENABLE(hsmbus);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->MasterTxCpltCallback(hsmbus);
+#else
+ HAL_SMBUS_MasterTxCpltCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
+ {
+ /* Store Last receive data if any */
+ if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_RXNE) != RESET)
+ {
+ /* Read data from RXDR */
+ *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
+
+ /* Increment Buffer pointer */
+ hsmbus->pBuffPtr++;
+
+ if ((hsmbus->XferSize > 0U))
+ {
+ hsmbus->XferSize--;
+ hsmbus->XferCount--;
+ }
+ }
+
+ /* Disable Interrupt */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
+
+ /* Clear STOP Flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ SMBUS_RESET_CR2(hsmbus);
+
+ hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->MasterRxCpltCallback(hsmbus);
+#else
+ HAL_SMBUS_MasterRxCpltCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_RXNE) != RESET)
+ {
+ /* Read data from RXDR */
+ *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
+
+ /* Increment Buffer pointer */
+ hsmbus->pBuffPtr++;
+
+ /* Increment Size counter */
+ hsmbus->XferSize--;
+ hsmbus->XferCount--;
+ }
+ else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TXIS) != RESET)
+ {
+ /* Write data to TXDR */
+ hsmbus->Instance->TXDR = *hsmbus->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hsmbus->pBuffPtr++;
+
+ /* Increment Size counter */
+ hsmbus->XferSize--;
+ hsmbus->XferCount--;
+ }
+ else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TCR) != RESET)
+ {
+ if ((hsmbus->XferCount != 0U) && (hsmbus->XferSize == 0U))
+ {
+ DevAddress = (uint16_t)(hsmbus->Instance->CR2 & I2C_CR2_SADD);
+
+ if (hsmbus->XferCount > MAX_NBYTE_SIZE)
+ {
+ SMBUS_TransferConfig(hsmbus, DevAddress, MAX_NBYTE_SIZE, (SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE)), SMBUS_NO_STARTSTOP);
+ hsmbus->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hsmbus->XferSize = hsmbus->XferCount;
+ SMBUS_TransferConfig(hsmbus, DevAddress, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions, SMBUS_NO_STARTSTOP);
+ /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */
+ /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
+ if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
+ {
+ hsmbus->XferSize--;
+ hsmbus->XferCount--;
+ }
+ }
+ }
+ else if ((hsmbus->XferCount == 0U) && (hsmbus->XferSize == 0U))
+ {
+ /* Call TxCpltCallback() if no stop mode is set */
+ if (SMBUS_GET_STOP_MODE(hsmbus) != SMBUS_AUTOEND_MODE)
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
+ {
+ /* Disable Interrupt */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
+ hsmbus->PreviousState = hsmbus->State;
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->MasterTxCpltCallback(hsmbus);
+#else
+ HAL_SMBUS_MasterTxCpltCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
+ {
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
+ hsmbus->PreviousState = hsmbus->State;
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->MasterRxCpltCallback(hsmbus);
+#else
+ HAL_SMBUS_MasterRxCpltCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TC) != RESET)
+ {
+ if (hsmbus->XferCount == 0U)
+ {
+ /* Specific use case for Quick command */
+ if (hsmbus->pBuffPtr == NULL)
+ {
+ /* Generate a Stop command */
+ hsmbus->Instance->CR2 |= I2C_CR2_STOP;
+ }
+ /* Call TxCpltCallback() if no stop mode is set */
+ else if (SMBUS_GET_STOP_MODE(hsmbus) != SMBUS_AUTOEND_MODE)
+ {
+ /* No Generate Stop, to permit restart mode */
+ /* The stop will be done at the end of transfer, when SMBUS_AUTOEND_MODE enable */
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_TX)
+ {
+ /* Disable Interrupt */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
+ hsmbus->PreviousState = hsmbus->State;
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->MasterTxCpltCallback(hsmbus);
+#else
+ HAL_SMBUS_MasterTxCpltCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ else if (hsmbus->State == HAL_SMBUS_STATE_MASTER_BUSY_RX)
+ {
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
+ hsmbus->PreviousState = hsmbus->State;
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->MasterRxCpltCallback(hsmbus);
+#else
+ HAL_SMBUS_MasterRxCpltCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ return HAL_OK;
+}
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param StatusFlags Value of Interrupt Flags.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SMBUS_Slave_ISR(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t StatusFlags)
+{
+ uint8_t TransferDirection;
+ uint16_t SlaveAddrCode;
+
+ /* Process Locked */
+ __HAL_LOCK(hsmbus);
+
+ if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_AF) != RESET)
+ {
+ /* Check that SMBUS transfer finished */
+ /* if yes, normal usecase, a NACK is sent by the HOST when Transfer is finished */
+ /* Mean XferCount == 0*/
+ /* So clear Flag NACKF only */
+ if (hsmbus->XferCount == 0U)
+ {
+ /* Clear NACK Flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+ }
+ else
+ {
+ /* if no, error usecase, a Non-Acknowledge of last Data is generated by the HOST*/
+ /* Clear NACK Flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF);
+
+ /* Set HAL State to "Idle" State, mean to LISTEN state */
+ /* So reset Slave Busy state */
+ hsmbus->PreviousState = hsmbus->State;
+ hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_TX);
+ hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_RX);
+
+ /* Disable RX/TX Interrupts, keep only ADDR Interrupt */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX | SMBUS_IT_TX);
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ACKF;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the Error callback to inform upper layer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->ErrorCallback(hsmbus);
+#else
+ HAL_SMBUS_ErrorCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ }
+ else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_ADDR) != RESET)
+ {
+ TransferDirection = (uint8_t)(SMBUS_GET_DIR(hsmbus));
+ SlaveAddrCode = (uint16_t)(SMBUS_GET_ADDR_MATCH(hsmbus));
+
+ /* Disable ADDR interrupt to prevent multiple ADDRInterrupt*/
+ /* Other ADDRInterrupt will be treat in next Listen usecase */
+ __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_ADDRI);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call Slave Addr callback */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->AddrCallback(hsmbus, TransferDirection, SlaveAddrCode);
+#else
+ HAL_SMBUS_AddrCallback(hsmbus, TransferDirection, SlaveAddrCode);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ else if ((SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_RXNE) != RESET) || (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TCR) != RESET))
+ {
+ if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_RX) == HAL_SMBUS_STATE_SLAVE_BUSY_RX)
+ {
+ /* Read data from RXDR */
+ *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
+
+ /* Increment Buffer pointer */
+ hsmbus->pBuffPtr++;
+
+ hsmbus->XferSize--;
+ hsmbus->XferCount--;
+
+ if (hsmbus->XferCount == 1U)
+ {
+ /* Receive last Byte, can be PEC byte in case of PEC BYTE enabled */
+ /* or only the last Byte of Transfer */
+ /* So reset the RELOAD bit mode */
+ hsmbus->XferOptions &= ~SMBUS_RELOAD_MODE;
+ SMBUS_TransferConfig(hsmbus, 0, 1, hsmbus->XferOptions, SMBUS_NO_STARTSTOP);
+ }
+ else if (hsmbus->XferCount == 0U)
+ {
+ /* Last Byte is received, disable Interrupt */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX);
+
+ /* Remove HAL_SMBUS_STATE_SLAVE_BUSY_RX, keep only HAL_SMBUS_STATE_LISTEN */
+ hsmbus->PreviousState = hsmbus->State;
+ hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_RX);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->SlaveRxCpltCallback(hsmbus);
+#else
+ HAL_SMBUS_SlaveRxCpltCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Set Reload for next Bytes */
+ SMBUS_TransferConfig(hsmbus, 0, 1, SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE), SMBUS_NO_STARTSTOP);
+
+ /* Ack last Byte Read */
+ hsmbus->Instance->CR2 &= ~I2C_CR2_NACK;
+ }
+ }
+ else if ((hsmbus->State & HAL_SMBUS_STATE_SLAVE_BUSY_TX) == HAL_SMBUS_STATE_SLAVE_BUSY_TX)
+ {
+ if ((hsmbus->XferCount != 0U) && (hsmbus->XferSize == 0U))
+ {
+ if (hsmbus->XferCount > MAX_NBYTE_SIZE)
+ {
+ SMBUS_TransferConfig(hsmbus, 0, MAX_NBYTE_SIZE, (SMBUS_RELOAD_MODE | (hsmbus->XferOptions & SMBUS_SENDPEC_MODE)), SMBUS_NO_STARTSTOP);
+ hsmbus->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hsmbus->XferSize = hsmbus->XferCount;
+ SMBUS_TransferConfig(hsmbus, 0, (uint8_t)hsmbus->XferSize, hsmbus->XferOptions, SMBUS_NO_STARTSTOP);
+ /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */
+ /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */
+ if (SMBUS_GET_PEC_MODE(hsmbus) != 0UL)
+ {
+ hsmbus->XferSize--;
+ hsmbus->XferCount--;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ else if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_TXIS) != RESET)
+ {
+ /* Write data to TXDR only if XferCount not reach "0" */
+ /* A TXIS flag can be set, during STOP treatment */
+ /* Check if all 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 (hsmbus->XferCount > 0U)
+ {
+ /* Write data to TXDR */
+ hsmbus->Instance->TXDR = *hsmbus->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hsmbus->pBuffPtr++;
+
+ hsmbus->XferCount--;
+ hsmbus->XferSize--;
+ }
+
+ if (hsmbus->XferCount == 0U)
+ {
+ /* Last Byte is Transmitted */
+ /* Remove HAL_SMBUS_STATE_SLAVE_BUSY_TX, keep only HAL_SMBUS_STATE_LISTEN */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_TX);
+ hsmbus->PreviousState = hsmbus->State;
+ hsmbus->State &= ~((uint32_t)HAL_SMBUS_STATE_SLAVE_BUSY_TX);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->SlaveTxCpltCallback(hsmbus);
+#else
+ HAL_SMBUS_SlaveTxCpltCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Check if STOPF is set */
+ if (SMBUS_CHECK_FLAG(StatusFlags, SMBUS_FLAG_STOPF) != RESET)
+ {
+ if ((hsmbus->State & HAL_SMBUS_STATE_LISTEN) == HAL_SMBUS_STATE_LISTEN)
+ {
+ /* Store Last receive data if any */
+ if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_RXNE) != RESET)
+ {
+ /* Read data from RXDR */
+ *hsmbus->pBuffPtr = (uint8_t)(hsmbus->Instance->RXDR);
+
+ /* Increment Buffer pointer */
+ hsmbus->pBuffPtr++;
+
+ if ((hsmbus->XferSize > 0U))
+ {
+ hsmbus->XferSize--;
+ hsmbus->XferCount--;
+ }
+ }
+
+ /* Disable RX and TX Interrupts */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_RX | SMBUS_IT_TX);
+
+ /* Disable ADDR Interrupt */
+ SMBUS_Disable_IRQ(hsmbus, SMBUS_IT_ADDR);
+
+ /* Disable Address Acknowledge */
+ hsmbus->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Clear Configuration Register 2 */
+ SMBUS_RESET_CR2(hsmbus);
+
+ /* Clear STOP Flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_STOPF);
+
+ /* Clear ADDR flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ADDR);
+
+ hsmbus->XferOptions = 0;
+ hsmbus->PreviousState = hsmbus->State;
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->ListenCpltCallback(hsmbus);
+#else
+ HAL_SMBUS_ListenCpltCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ return HAL_OK;
+}
+/**
+ * @brief Manage the enabling of Interrupts.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param InterruptRequest Value of @ref SMBUS_Interrupt_configuration_definition.
+ * @retval HAL status
+ */
+static void SMBUS_Enable_IRQ(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest)
+{
+ uint32_t tmpisr = 0UL;
+
+ if ((InterruptRequest & SMBUS_IT_ALERT) == SMBUS_IT_ALERT)
+ {
+ /* Enable ERR interrupt */
+ tmpisr |= SMBUS_IT_ERRI;
+ }
+
+ if ((InterruptRequest & SMBUS_IT_ADDR) == SMBUS_IT_ADDR)
+ {
+ /* Enable ADDR, STOP interrupt */
+ tmpisr |= SMBUS_IT_ADDRI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_ERRI;
+ }
+
+ if ((InterruptRequest & SMBUS_IT_TX) == SMBUS_IT_TX)
+ {
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ tmpisr |= SMBUS_IT_ERRI | SMBUS_IT_TCI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_TXI;
+ }
+
+ if ((InterruptRequest & SMBUS_IT_RX) == SMBUS_IT_RX)
+ {
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ tmpisr |= SMBUS_IT_ERRI | SMBUS_IT_TCI | SMBUS_IT_STOPI | SMBUS_IT_NACKI | SMBUS_IT_RXI;
+ }
+
+ /* Enable interrupts only at the end */
+ /* to avoid the risk of SMBUS interrupt handle execution before */
+ /* all interrupts requested done */
+ __HAL_SMBUS_ENABLE_IT(hsmbus, tmpisr);
+}
+/**
+ * @brief Manage the disabling of Interrupts.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param InterruptRequest Value of @ref SMBUS_Interrupt_configuration_definition.
+ * @retval HAL status
+ */
+static void SMBUS_Disable_IRQ(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t InterruptRequest)
+{
+ uint32_t tmpisr = 0UL;
+ uint32_t tmpstate = hsmbus->State;
+
+ if ((tmpstate == HAL_SMBUS_STATE_READY) && ((InterruptRequest & SMBUS_IT_ALERT) == SMBUS_IT_ALERT))
+ {
+ /* Disable ERR interrupt */
+ tmpisr |= SMBUS_IT_ERRI;
+ }
+
+ if ((InterruptRequest & SMBUS_IT_TX) == SMBUS_IT_TX)
+ {
+ /* Disable TC, STOP, NACK and TXI interrupt */
+ tmpisr |= SMBUS_IT_TCI | SMBUS_IT_TXI;
+
+ if ((SMBUS_GET_ALERT_ENABLED(hsmbus) == 0UL)
+ && ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN))
+ {
+ /* Disable ERR interrupt */
+ tmpisr |= SMBUS_IT_ERRI;
+ }
+
+ if ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN)
+ {
+ /* Disable STOP and NACK interrupt */
+ tmpisr |= SMBUS_IT_STOPI | SMBUS_IT_NACKI;
+ }
+ }
+
+ if ((InterruptRequest & SMBUS_IT_RX) == SMBUS_IT_RX)
+ {
+ /* Disable TC, STOP, NACK and RXI interrupt */
+ tmpisr |= SMBUS_IT_TCI | SMBUS_IT_RXI;
+
+ if ((SMBUS_GET_ALERT_ENABLED(hsmbus) == 0UL)
+ && ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN))
+ {
+ /* Disable ERR interrupt */
+ tmpisr |= SMBUS_IT_ERRI;
+ }
+
+ if ((tmpstate & HAL_SMBUS_STATE_LISTEN) != HAL_SMBUS_STATE_LISTEN)
+ {
+ /* Disable STOP and NACK interrupt */
+ tmpisr |= SMBUS_IT_STOPI | SMBUS_IT_NACKI;
+ }
+ }
+
+ if ((InterruptRequest & SMBUS_IT_ADDR) == SMBUS_IT_ADDR)
+ {
+ /* Disable ADDR, STOP and NACK interrupt */
+ tmpisr |= SMBUS_IT_ADDRI | SMBUS_IT_STOPI | SMBUS_IT_NACKI;
+
+ if (SMBUS_GET_ALERT_ENABLED(hsmbus) == 0UL)
+ {
+ /* Disable ERR interrupt */
+ tmpisr |= SMBUS_IT_ERRI;
+ }
+ }
+
+ /* Disable interrupts only at the end */
+ /* to avoid a breaking situation like at "t" time */
+ /* all disable interrupts request are not done */
+ __HAL_SMBUS_DISABLE_IT(hsmbus, tmpisr);
+}
+
+/**
+ * @brief SMBUS interrupts error handler.
+ * @param hsmbus SMBUS handle.
+ * @retval None
+ */
+static void SMBUS_ITErrorHandler(struct __SMBUS_HandleTypeDef *hsmbus)
+{
+ uint32_t itflags = READ_REG(hsmbus->Instance->ISR);
+ uint32_t itsources = READ_REG(hsmbus->Instance->CR1);
+ uint32_t tmpstate;
+ uint32_t tmperror;
+
+ /* SMBUS Bus error interrupt occurred ------------------------------------*/
+ if (((itflags & SMBUS_FLAG_BERR) == SMBUS_FLAG_BERR) && ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
+ {
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_BERR;
+
+ /* Clear BERR flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_BERR);
+ }
+
+ /* SMBUS Over-Run/Under-Run interrupt occurred ----------------------------------------*/
+ if (((itflags & SMBUS_FLAG_OVR) == SMBUS_FLAG_OVR) && ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
+ {
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_OVR;
+
+ /* Clear OVR flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_OVR);
+ }
+
+ /* SMBUS Arbitration Loss error interrupt occurred ------------------------------------*/
+ if (((itflags & SMBUS_FLAG_ARLO) == SMBUS_FLAG_ARLO) && ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
+ {
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ARLO;
+
+ /* Clear ARLO flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ARLO);
+ }
+
+ /* SMBUS Timeout error interrupt occurred ---------------------------------------------*/
+ if (((itflags & SMBUS_FLAG_TIMEOUT) == SMBUS_FLAG_TIMEOUT) && ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
+ {
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_BUSTIMEOUT;
+
+ /* Clear TIMEOUT flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_TIMEOUT);
+ }
+
+ /* SMBUS Alert error interrupt occurred -----------------------------------------------*/
+ if (((itflags & SMBUS_FLAG_ALERT) == SMBUS_FLAG_ALERT) && ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
+ {
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ALERT;
+
+ /* Clear ALERT flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ALERT);
+ }
+
+ /* SMBUS Packet Error Check error interrupt occurred ----------------------------------*/
+ if (((itflags & SMBUS_FLAG_PECERR) == SMBUS_FLAG_PECERR) && ((itsources & SMBUS_IT_ERRI) == SMBUS_IT_ERRI))
+ {
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_PECERR;
+
+ /* Clear PEC error flag */
+ __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_PECERR);
+ }
+
+ /* Store current volatile hsmbus->State, misra rule */
+ tmperror = hsmbus->ErrorCode;
+
+ /* Call the Error Callback in case of Error detected */
+ if ((tmperror != HAL_SMBUS_ERROR_NONE) && (tmperror != HAL_SMBUS_ERROR_ACKF))
+ {
+ /* Do not Reset the HAL state in case of ALERT error */
+ if ((tmperror & HAL_SMBUS_ERROR_ALERT) != HAL_SMBUS_ERROR_ALERT)
+ {
+ /* Store current volatile hsmbus->State, misra rule */
+ tmpstate = hsmbus->State;
+
+ if (((tmpstate & HAL_SMBUS_STATE_SLAVE_BUSY_TX) == HAL_SMBUS_STATE_SLAVE_BUSY_TX)
+ || ((tmpstate & HAL_SMBUS_STATE_SLAVE_BUSY_RX) == HAL_SMBUS_STATE_SLAVE_BUSY_RX))
+ {
+ /* Reset only HAL_SMBUS_STATE_SLAVE_BUSY_XX */
+ /* keep HAL_SMBUS_STATE_LISTEN if set */
+ hsmbus->PreviousState = HAL_SMBUS_STATE_READY;
+ hsmbus->State = HAL_SMBUS_STATE_LISTEN;
+ }
+ }
+
+ /* Call the Error callback to inform upper layer */
+#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1)
+ hsmbus->ErrorCallback(hsmbus);
+#else
+ HAL_SMBUS_ErrorCallback(hsmbus);
+#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Handle SMBUS Communication Timeout.
+ * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains
+ * the configuration information for the specified SMBUS.
+ * @param Flag Specifies the SMBUS flag to check.
+ * @param Status The new Flag status (SET or RESET).
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SMBUS_WaitOnFlagUntilTimeout(struct __SMBUS_HandleTypeDef *hsmbus, uint32_t Flag, FlagStatus Status, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Wait until flag is set */
+ while ((FlagStatus)(__HAL_SMBUS_GET_FLAG(hsmbus, Flag)) == Status)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+ {
+ hsmbus->PreviousState = hsmbus->State;
+ hsmbus->State = HAL_SMBUS_STATE_READY;
+
+ /* Update SMBUS error code */
+ hsmbus->ErrorCode |= HAL_SMBUS_ERROR_HALTIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsmbus);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle SMBUSx communication when starting transfer or during transfer (TC or TCR flag are set).
+ * @param hsmbus SMBUS 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 SMBUS START condition generation.
+ * This parameter can be one or a combination of the following values:
+ * @arg @ref SMBUS_RELOAD_MODE Enable Reload mode.
+ * @arg @ref SMBUS_AUTOEND_MODE Enable Automatic end mode.
+ * @arg @ref SMBUS_SOFTEND_MODE Enable Software end mode and Reload mode.
+ * @arg @ref SMBUS_SENDPEC_MODE Enable Packet Error Calculation mode.
+ * @param Request New state of the SMBUS START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref SMBUS_NO_STARTSTOP Don't Generate stop and start condition.
+ * @arg @ref SMBUS_GENERATE_STOP Generate stop condition (Size should be set to 0).
+ * @arg @ref SMBUS_GENERATE_START_READ Generate Restart for read request.
+ * @arg @ref SMBUS_GENERATE_START_WRITE Generate Restart for write request.
+ * @retval None
+ */
+static void SMBUS_TransferConfig(struct __SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request)
+{
+ /* Check the parameters */
+ assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance));
+ assert_param(IS_SMBUS_TRANSFER_MODE(Mode));
+ assert_param(IS_SMBUS_TRANSFER_REQUEST(Request));
+
+ /* update CR2 register */
+ MODIFY_REG(hsmbus->Instance->CR2, ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31UL - I2C_CR2_RD_WRN_Pos))) | I2C_CR2_START | I2C_CR2_STOP | I2C_CR2_PECBYTE)), \
+ (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | (uint32_t)Mode | (uint32_t)Request));
+}
+
+/**
+ * @brief Convert SMBUSx OTHER_xxx XferOptions to functionnal XferOptions.
+ * @param hsmbus SMBUS handle.
+ * @retval None
+ */
+static void SMBUS_ConvertOtherXferOptions(struct __SMBUS_HandleTypeDef *hsmbus)
+{
+ /* if user set XferOptions to SMBUS_OTHER_FRAME_NO_PEC */
+ /* it request implicitly to generate a restart condition */
+ /* set XferOptions to SMBUS_FIRST_FRAME */
+ if (hsmbus->XferOptions == SMBUS_OTHER_FRAME_NO_PEC)
+ {
+ hsmbus->XferOptions = SMBUS_FIRST_FRAME;
+ }
+ /* else if user set XferOptions to SMBUS_OTHER_FRAME_WITH_PEC */
+ /* it request implicitly to generate a restart condition */
+ /* set XferOptions to SMBUS_FIRST_FRAME | SMBUS_SENDPEC_MODE */
+ else if (hsmbus->XferOptions == SMBUS_OTHER_FRAME_WITH_PEC)
+ {
+ hsmbus->XferOptions = SMBUS_FIRST_FRAME | SMBUS_SENDPEC_MODE;
+ }
+ /* else if user set XferOptions to SMBUS_OTHER_AND_LAST_FRAME_NO_PEC */
+ /* it request implicitly to generate a restart condition */
+ /* then generate a stop condition at the end of transfer */
+ /* set XferOptions to SMBUS_FIRST_AND_LAST_FRAME_NO_PEC */
+ else if (hsmbus->XferOptions == SMBUS_OTHER_AND_LAST_FRAME_NO_PEC)
+ {
+ hsmbus->XferOptions = SMBUS_FIRST_AND_LAST_FRAME_NO_PEC;
+ }
+ /* else if user set XferOptions to SMBUS_OTHER_AND_LAST_FRAME_WITH_PEC */
+ /* it request implicitly to generate a restart condition */
+ /* then generate a stop condition at the end of transfer */
+ /* set XferOptions to SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC */
+ else if (hsmbus->XferOptions == SMBUS_OTHER_AND_LAST_FRAME_WITH_PEC)
+ {
+ hsmbus->XferOptions = SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+/**
+ * @}
+ */
+
+#endif /* HAL_SMBUS_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_spdifrx.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_spdifrx.c
new file mode 100644
index 0000000000..2d27b27b15
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_spdifrx.c
@@ -0,0 +1,1635 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_spdifrx.c
+ * @author MCD Application Team
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the SPDIFRX audio interface:
+ * + Initialization and Configuration
+ * + Data transfers functions
+ * + DMA transfers management
+ * + Interrupts and flags management
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The SPDIFRX HAL driver can be used as follow:
+
+ (#) Declare SPDIFRX_HandleTypeDef handle structure.
+ (#) Initialize the SPDIFRX low level resources by implement the HAL_SPDIFRX_MspInit() API:
+ (##) Enable the SPDIFRX interface clock.
+ (##) SPDIFRX pins configuration:
+ (+++) Enable the clock for the SPDIFRX GPIOs.
+ (+++) Configure these SPDIFRX pins as alternate function pull-up.
+ (##) NVIC configuration if you need to use interrupt process (HAL_SPDIFRX_ReceiveCtrlFlow_IT() and HAL_SPDIFRX_ReceiveDataFlow_IT() API's).
+ (+++) Configure the SPDIFRX interrupt priority.
+ (+++) Enable the NVIC SPDIFRX IRQ handle.
+ (##) DMA Configuration if you need to use DMA process (HAL_SPDIFRX_ReceiveDataFlow_DMA() and HAL_SPDIFRX_ReceiveCtrlFlow_DMA() API's).
+ (+++) Declare a DMA handle structure for the reception of the Data Flow channel.
+ (+++) Declare a DMA handle structure for the reception of the Control Flow channel.
+ (+++) Enable the DMAx interface clock.
+ (+++) Configure the declared DMA handle structure CtrlRx/DataRx with the required parameters.
+ (+++) Configure the DMA Channel.
+ (+++) Associate the initialized DMA handle to the SPDIFRX DMA CtrlRx/DataRx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
+ DMA CtrlRx/DataRx channel.
+
+ (#) Program the input selection, re-tries number, wait for activity, channel status selection, data format, stereo mode and masking of user bits
+ using HAL_SPDIFRX_Init() function.
+
+ -@- The specific SPDIFRX interrupts (RXNE/CSRNE and Error Interrupts) will be managed using the macros
+ __SPDIFRX_ENABLE_IT() and __SPDIFRX_DISABLE_IT() inside the receive process.
+ -@- Make sure that ck_spdif clock is configured.
+
+ (#) Three operation modes are available within this driver :
+
+ *** Polling mode for reception operation (for debug purpose) ***
+ ================================================================
+ [..]
+ (+) Receive data flow in blocking mode using HAL_SPDIFRX_ReceiveDataFlow()
+ (+) Receive control flow of data in blocking mode using HAL_SPDIFRX_ReceiveCtrlFlow()
+
+ *** Interrupt mode for reception operation ***
+ =========================================
+ [..]
+ (+) Receive an amount of data (Data Flow) in non blocking mode using HAL_SPDIFRX_ReceiveDataFlow_IT()
+ (+) Receive an amount of data (Control Flow) in non blocking mode using HAL_SPDIFRX_ReceiveCtrlFlow_IT()
+ (+) At reception end of half transfer HAL_SPDIFRX_RxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_SPDIFRX_RxHalfCpltCallback
+ (+) At reception end of transfer HAL_SPDIFRX_RxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_SPDIFRX_RxCpltCallback
+ (+) In case of transfer Error, HAL_SPDIFRX_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_SPDIFRX_ErrorCallback
+
+ *** DMA mode for reception operation ***
+ ========================================
+ [..]
+ (+) Receive an amount of data (Data Flow) in non blocking mode (DMA) using HAL_SPDIFRX_ReceiveDataFlow_DMA()
+ (+) Receive an amount of data (Control Flow) in non blocking mode (DMA) using HAL_SPDIFRX_ReceiveCtrlFlow_DMA()
+ (+) At reception end of half transfer HAL_SPDIFRX_RxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_SPDIFRX_RxHalfCpltCallback
+ (+) At reception end of transfer HAL_SPDIFRX_RxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_SPDIFRX_RxCpltCallback
+ (+) In case of transfer Error, HAL_SPDIFRX_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_SPDIFRX_ErrorCallback
+ (+) Stop the DMA Transfer using HAL_SPDIFRX_DMAStop()
+
+ *** SPDIFRX HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in SPDIFRX HAL driver.
+ (+) __HAL_SPDIFRX_IDLE: Disable the specified SPDIFRX peripheral (IDEL State)
+ (+) __HAL_SPDIFRX_SYNC: Enable the synchronization state of the specified SPDIFRX peripheral (SYNC State)
+ (+) __HAL_SPDIFRX_RCV: Enable the receive state of the specified SPDIFRX peripheral (RCV State)
+ (+) __HAL_SPDIFRX_ENABLE_IT : Enable the specified SPDIFRX interrupts
+ (+) __HAL_SPDIFRX_DISABLE_IT : Disable the specified SPDIFRX interrupts
+ (+) __HAL_SPDIFRX_GET_FLAG: Check whether the specified SPDIFRX flag is set or not.
+
+ [..]
+ (@) You can refer to the SPDIFRX HAL driver header file for more useful macros
+
+ *** Callback registration ***
+ =============================================
+
+ The compilation define USE_HAL_SPDIFRX_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use HAL_SPDIFRX_RegisterCallback() funtion to register an interrupt callback.
+
+ The HAL_SPDIFRX_RegisterCallback() function allows to register the following callbacks:
+ (+) RxHalfCpltCallback : SPDIFRX Data flow half completed callback.
+ (+) RxCpltCallback : SPDIFRX Data flow completed callback.
+ (+) CxHalfCpltCallback : SPDIFRX Control flow half completed callback.
+ (+) CxCpltCallback : SPDIFRX Control flow completed callback.
+ (+) ErrorCallback : SPDIFRX error callback.
+ (+) MspInitCallback : SPDIFRX MspInit.
+ (+) MspDeInitCallback : SPDIFRX MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use HAL_SPDIFRX_UnRegisterCallback() function to reset a callback to the default
+ weak function.
+ The HAL_SPDIFRX_UnRegisterCallback() function takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset the following callbacks:
+ (+) RxHalfCpltCallback : SPDIFRX Data flow half completed callback.
+ (+) RxCpltCallback : SPDIFRX Data flow completed callback.
+ (+) CxHalfCpltCallback : SPDIFRX Control flow half completed callback.
+ (+) CxCpltCallback : SPDIFRX Control flow completed callback.
+ (+) ErrorCallback : SPDIFRX error callback.
+ (+) MspInitCallback : SPDIFRX MspInit.
+ (+) MspDeInitCallback : SPDIFRX MspDeInit.
+
+ By default, after the HAL_SPDIFRX_Init() and when the state is HAL_SPDIFRX_STATE_RESET
+ all callbacks are set to the corresponding weak functions :
+ HAL_SPDIFRX_RxHalfCpltCallback() , HAL_SPDIFRX_RxCpltCallback(), HAL_SPDIFRX_CxHalfCpltCallback(),
+ HAL_SPDIFRX_CxCpltCallback() and HAL_SPDIFRX_ErrorCallback()
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak function in the HAL_SPDIFRX_Init()/ HAL_SPDIFRX_DeInit() only when
+ these callbacks pointers are NULL (not registered beforehand).
+ If not, MspInit or MspDeInit callbacks pointers are not null, the HAL_SPDIFRX_Init() / HAL_SPDIFRX_DeInit()
+ keep and use the user MspInit/MspDeInit functions (registered beforehand)
+
+ Callbacks can be registered/unregistered in HAL_SPDIFRX_STATE_READY state only.
+ Exception done MspInit/MspDeInit callbacks that can be registered/unregistered
+ in HAL_SPDIFRX_STATE_READY or HAL_SPDIFRX_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_SPDIFRX_RegisterCallback() before calling HAL_SPDIFRX_DeInit()
+ or HAL_SPDIFRX_Init() function.
+
+ When The compilation define USE_HAL_SPDIFRX_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SPDIFRX SPDIFRX
+ * @brief SPDIFRX HAL module driver
+ * @{
+ */
+
+#ifdef HAL_SPDIFRX_MODULE_ENABLED
+#if defined (SPDIFRX)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define SPDIFRX_TIMEOUT_VALUE 0xFFFFU
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup SPDIFRX_Private_Functions
+ * @{
+ */
+static void SPDIFRX_DMARxCplt(DMA_HandleTypeDef *hdma);
+static void SPDIFRX_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
+static void SPDIFRX_DMACxCplt(DMA_HandleTypeDef *hdma);
+static void SPDIFRX_DMACxHalfCplt(DMA_HandleTypeDef *hdma);
+static void SPDIFRX_DMAError(DMA_HandleTypeDef *hdma);
+static void SPDIFRX_ReceiveControlFlow_IT(SPDIFRX_HandleTypeDef *hspdif);
+static void SPDIFRX_ReceiveDataFlow_IT(SPDIFRX_HandleTypeDef *hspdif);
+static HAL_StatusTypeDef SPDIFRX_WaitOnFlagUntilTimeout(SPDIFRX_HandleTypeDef *hspdif, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t tickstart);
+/**
+ * @}
+ */
+/* Exported functions ---------------------------------------------------------*/
+
+/** @defgroup SPDIFRX_Exported_Functions SPDIFRX Exported Functions
+ * @{
+ */
+
+/** @defgroup SPDIFRX_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 SPDIFRX peripheral:
+
+ (+) User must Implement HAL_SPDIFRX_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_SPDIFRX_Init() to configure the SPDIFRX peripheral with
+ the selected configuration:
+ (++) Input Selection (IN0, IN1,...)
+ (++) Maximum allowed re-tries during synchronization phase
+ (++) Wait for activity on SPDIF selected input
+ (++) Channel status selection (from channel A or B)
+ (++) Data format (LSB, MSB, ...)
+ (++) Stereo mode
+ (++) User bits masking (PT,C,U,V,...)
+
+ (+) Call the function HAL_SPDIFRX_DeInit() to restore the default configuration
+ of the selected SPDIFRXx peripheral.
+ @endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the SPDIFRX according to the specified parameters
+ * in the SPDIFRX_InitTypeDef and create the associated handle.
+ * @param hspdif SPDIFRX handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_Init(SPDIFRX_HandleTypeDef *hspdif)
+{
+ uint32_t tmpreg;
+
+ /* Check the SPDIFRX handle allocation */
+ if(hspdif == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the SPDIFRX parameters */
+ assert_param(IS_STEREO_MODE(hspdif->Init.StereoMode));
+ assert_param(IS_SPDIFRX_INPUT_SELECT(hspdif->Init.InputSelection));
+ assert_param(IS_SPDIFRX_MAX_RETRIES(hspdif->Init.Retries));
+ assert_param(IS_SPDIFRX_WAIT_FOR_ACTIVITY(hspdif->Init.WaitForActivity));
+ assert_param(IS_SPDIFRX_CHANNEL(hspdif->Init.ChannelSelection));
+ assert_param(IS_SPDIFRX_DATA_FORMAT(hspdif->Init.DataFormat));
+ assert_param(IS_PREAMBLE_TYPE_MASK(hspdif->Init.PreambleTypeMask));
+ assert_param(IS_CHANNEL_STATUS_MASK(hspdif->Init.ChannelStatusMask));
+ assert_param(IS_VALIDITY_MASK(hspdif->Init.ValidityBitMask));
+ assert_param(IS_PARITY_ERROR_MASK(hspdif->Init.ParityErrorMask));
+ assert_param(IS_SYMBOL_CLOCK_GEN(hspdif->Init.SymbolClockGen));
+ assert_param(IS_SYMBOL_CLOCK_GEN(hspdif->Init.BackupSymbolClockGen));
+
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+ if(hspdif->State == HAL_SPDIFRX_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hspdif->Lock = HAL_UNLOCKED;
+
+ hspdif->RxHalfCpltCallback = HAL_SPDIFRX_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ hspdif->RxCpltCallback = HAL_SPDIFRX_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ hspdif->CxHalfCpltCallback = HAL_SPDIFRX_CxHalfCpltCallback; /* Legacy weak CxHalfCpltCallback */
+ hspdif->CxCpltCallback = HAL_SPDIFRX_CxCpltCallback; /* Legacy weak CxCpltCallback */
+ hspdif->ErrorCallback = HAL_SPDIFRX_ErrorCallback; /* Legacy weak ErrorCallback */
+
+ if(hspdif->MspInitCallback == NULL)
+ {
+ hspdif->MspInitCallback = HAL_SPDIFRX_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware */
+ hspdif->MspInitCallback(hspdif);
+ }
+#else
+ if(hspdif->State == HAL_SPDIFRX_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hspdif->Lock = HAL_UNLOCKED;
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ HAL_SPDIFRX_MspInit(hspdif);
+ }
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+
+ /* SPDIFRX peripheral state is BUSY */
+ hspdif->State = HAL_SPDIFRX_STATE_BUSY;
+
+ /* Disable SPDIFRX interface (IDLE State) */
+ __HAL_SPDIFRX_IDLE(hspdif);
+
+ /* Reset the old SPDIFRX CR configuration */
+ tmpreg = hspdif->Instance->CR;
+
+ tmpreg &= ~(SPDIFRX_CR_RXSTEO | SPDIFRX_CR_DRFMT | SPDIFRX_CR_PMSK |
+ SPDIFRX_CR_VMSK | SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK |
+ SPDIFRX_CR_CHSEL | SPDIFRX_CR_NBTR | SPDIFRX_CR_WFA |
+ SPDIFRX_CR_CKSEN | SPDIFRX_CR_CKSBKPEN |
+ SPDIFRX_CR_INSEL);
+
+ /* Sets the new configuration of the SPDIFRX peripheral */
+ tmpreg |= (hspdif->Init.StereoMode |
+ hspdif->Init.InputSelection |
+ hspdif->Init.Retries |
+ hspdif->Init.WaitForActivity |
+ hspdif->Init.ChannelSelection |
+ hspdif->Init.DataFormat |
+ hspdif->Init.PreambleTypeMask |
+ hspdif->Init.ChannelStatusMask |
+ hspdif->Init.ValidityBitMask |
+ hspdif->Init.ParityErrorMask
+ );
+
+ if(hspdif->Init.SymbolClockGen == ENABLE)
+ {
+ tmpreg |= SPDIFRX_CR_CKSEN;
+ }
+
+ if(hspdif->Init.BackupSymbolClockGen == ENABLE)
+ {
+ tmpreg |= SPDIFRX_CR_CKSBKPEN;
+ }
+
+ hspdif->Instance->CR = tmpreg;
+
+ hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE;
+
+ /* SPDIFRX peripheral state is READY*/
+ hspdif->State = HAL_SPDIFRX_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the SPDIFRX peripheral
+ * @param hspdif SPDIFRX handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_DeInit(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Check the SPDIFRX handle allocation */
+ if(hspdif == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SPDIFRX_ALL_INSTANCE(hspdif->Instance));
+
+ hspdif->State = HAL_SPDIFRX_STATE_BUSY;
+
+ /* Disable SPDIFRX interface (IDLE state) */
+ __HAL_SPDIFRX_IDLE(hspdif);
+
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+ if(hspdif->MspDeInitCallback == NULL)
+ {
+ hspdif->MspDeInitCallback = HAL_SPDIFRX_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware */
+ hspdif->MspDeInitCallback(hspdif);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ HAL_SPDIFRX_MspDeInit(hspdif);
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+
+ hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE;
+
+ /* SPDIFRX peripheral state is RESET*/
+ hspdif->State = HAL_SPDIFRX_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief SPDIFRX MSP Init
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+__weak void HAL_SPDIFRX_MspInit(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspdif);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SPDIFRX_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SPDIFRX MSP DeInit
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+__weak void HAL_SPDIFRX_MspDeInit(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspdif);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SPDIFRX_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User SPDIFRX Callback
+ * To be used instead of the weak predefined callback
+ * @param hspdif SPDIFRX handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SPDIFRX_RX_HALF_CB_ID SPDIFRX Data flow half completed callback ID
+ * @arg @ref HAL_SPDIFRX_RX_CPLT_CB_ID SPDIFRX Data flow completed callback ID
+ * @arg @ref HAL_SPDIFRX_CX_HALF_CB_ID SPDIFRX Control flow half completed callback ID
+ * @arg @ref HAL_SPDIFRX_CX_CPLT_CB_ID SPDIFRX Control flow completed callback ID
+ * @arg @ref HAL_SPDIFRX_ERROR_CB_ID SPDIFRX error callback ID
+ * @arg @ref HAL_SPDIFRX_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_SPDIFRX_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_RegisterCallback(SPDIFRX_HandleTypeDef *hspdif, HAL_SPDIFRX_CallbackIDTypeDef CallbackID, pSPDIFRX_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hspdif);
+
+ if(HAL_SPDIFRX_STATE_READY == hspdif->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPDIFRX_RX_HALF_CB_ID :
+ hspdif->RxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_SPDIFRX_RX_CPLT_CB_ID :
+ hspdif->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_SPDIFRX_CX_HALF_CB_ID :
+ hspdif->CxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_SPDIFRX_CX_CPLT_CB_ID :
+ hspdif->CxCpltCallback = pCallback;
+ break;
+
+ case HAL_SPDIFRX_ERROR_CB_ID :
+ hspdif->ErrorCallback = pCallback;
+ break;
+
+ case HAL_SPDIFRX_MSPINIT_CB_ID :
+ hspdif->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SPDIFRX_MSPDEINIT_CB_ID :
+ hspdif->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_SPDIFRX_STATE_RESET == hspdif->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPDIFRX_MSPINIT_CB_ID :
+ hspdif->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SPDIFRX_MSPDEINIT_CB_ID :
+ hspdif->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hspdif);
+ return status;
+}
+
+/**
+ * @brief Unregister a SPDIFRX Callback
+ * SPDIFRX callabck is redirected to the weak predefined callback
+ * @param hspdif SPDIFRX handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SPDIFRX_RX_HALF_CB_ID SPDIFRX Data flow half completed callback ID
+ * @arg @ref HAL_SPDIFRX_RX_CPLT_CB_ID SPDIFRX Data flow completed callback ID
+ * @arg @ref HAL_SPDIFRX_CX_HALF_CB_ID SPDIFRX Control flow half completed callback ID
+ * @arg @ref HAL_SPDIFRX_CX_CPLT_CB_ID SPDIFRX Control flow completed callback ID
+ * @arg @ref HAL_SPDIFRX_ERROR_CB_ID SPDIFRX error callback ID
+ * @arg @ref HAL_SPDIFRX_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_SPDIFRX_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_UnRegisterCallback(SPDIFRX_HandleTypeDef *hspdif, HAL_SPDIFRX_CallbackIDTypeDef CallbackID)
+{
+HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hspdif);
+
+ if(HAL_SPDIFRX_STATE_READY == hspdif->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPDIFRX_RX_HALF_CB_ID :
+ hspdif->RxHalfCpltCallback = HAL_SPDIFRX_RxHalfCpltCallback;
+ break;
+
+ case HAL_SPDIFRX_RX_CPLT_CB_ID :
+ hspdif->RxCpltCallback = HAL_SPDIFRX_RxCpltCallback;
+ break;
+
+ case HAL_SPDIFRX_CX_HALF_CB_ID :
+ hspdif->CxHalfCpltCallback = HAL_SPDIFRX_CxHalfCpltCallback;
+ break;
+
+ case HAL_SPDIFRX_CX_CPLT_CB_ID :
+ hspdif->CxCpltCallback = HAL_SPDIFRX_CxCpltCallback;
+ break;
+
+ case HAL_SPDIFRX_ERROR_CB_ID :
+ hspdif->ErrorCallback = HAL_SPDIFRX_ErrorCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(HAL_SPDIFRX_STATE_RESET == hspdif->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPDIFRX_MSPINIT_CB_ID :
+ hspdif->MspInitCallback = HAL_SPDIFRX_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_SPDIFRX_MSPDEINIT_CB_ID :
+ hspdif->MspDeInitCallback = HAL_SPDIFRX_MspDeInit; /* Legacy weak MspInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hspdif);
+ return status;
+}
+
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+
+/**
+ * @brief Set the SPDIFRX data format according to the specified parameters in the SPDIFRX_InitTypeDef.
+ * @param hspdif SPDIFRX handle
+ * @param sDataFormat SPDIFRX data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_SetDataFormat(SPDIFRX_HandleTypeDef *hspdif, SPDIFRX_SetDataFormatTypeDef sDataFormat)
+{
+ uint32_t tmpreg;
+
+ /* Check the SPDIFRX handle allocation */
+ if(hspdif == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the SPDIFRX parameters */
+ assert_param(IS_STEREO_MODE(sDataFormat.StereoMode));
+ assert_param(IS_SPDIFRX_DATA_FORMAT(sDataFormat.DataFormat));
+ assert_param(IS_PREAMBLE_TYPE_MASK(sDataFormat.PreambleTypeMask));
+ assert_param(IS_CHANNEL_STATUS_MASK(sDataFormat.ChannelStatusMask));
+ assert_param(IS_VALIDITY_MASK(sDataFormat.ValidityBitMask));
+ assert_param(IS_PARITY_ERROR_MASK(sDataFormat.ParityErrorMask));
+
+ /* Reset the old SPDIFRX CR configuration */
+ tmpreg = hspdif->Instance->CR;
+
+ if(((tmpreg & SPDIFRX_STATE_RCV) == SPDIFRX_STATE_RCV) &&
+ (((tmpreg & SPDIFRX_CR_DRFMT) != sDataFormat.DataFormat) ||
+ ((tmpreg & SPDIFRX_CR_RXSTEO) != sDataFormat.StereoMode)))
+ {
+ return HAL_ERROR;
+ }
+
+ tmpreg &= ~(SPDIFRX_CR_RXSTEO | SPDIFRX_CR_DRFMT | SPDIFRX_CR_PMSK |
+ SPDIFRX_CR_VMSK | SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK);
+
+ /* Configure the new data format */
+ tmpreg |= (sDataFormat.StereoMode |
+ sDataFormat.DataFormat |
+ sDataFormat.PreambleTypeMask |
+ sDataFormat.ChannelStatusMask |
+ sDataFormat.ValidityBitMask |
+ sDataFormat.ParityErrorMask);
+
+ hspdif->Instance->CR = tmpreg;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPDIFRX_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 SPDIFRX data
+ transfers.
+
+ (#) There is two mode 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 start-up.
+ The end of the data processing will be indicated through the
+ dedicated SPDIFRX IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+
+ (#) Blocking mode functions are :
+ (++) HAL_SPDIFRX_ReceiveDataFlow()
+ (++) HAL_SPDIFRX_ReceiveCtrlFlow()
+ (+@) Do not use blocking mode to receive both control and data flow at the same time.
+
+ (#) No-Blocking mode functions with Interrupt are :
+ (++) HAL_SPDIFRX_ReceiveCtrlFlow_IT()
+ (++) HAL_SPDIFRX_ReceiveDataFlow_IT()
+
+ (#) No-Blocking mode functions with DMA are :
+ (++) HAL_SPDIFRX_ReceiveCtrlFlow_DMA()
+ (++) HAL_SPDIFRX_ReceiveDataFlow_DMA()
+
+ (#) A set of Transfer Complete Callbacks are provided in No_Blocking mode:
+ (++) HAL_SPDIFRX_RxCpltCallback()
+ (++) HAL_SPDIFRX_CxCpltCallback()
+
+@endverbatim
+* @{
+*/
+
+/**
+ * @brief Receives an amount of data (Data Flow) in blocking mode.
+ * @param hspdif pointer to SPDIFRX_HandleTypeDef structure that contains
+ * the configuration information for SPDIFRX 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_SPDIFRX_ReceiveDataFlow(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint16_t sizeCounter = Size;
+ uint32_t *pTmpBuf = pData;
+
+ if((pData == NULL ) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if(hspdif->State == HAL_SPDIFRX_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hspdif);
+
+ hspdif->State = HAL_SPDIFRX_STATE_BUSY;
+
+ /* Start synchronisation */
+ __HAL_SPDIFRX_SYNC(hspdif);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until SYNCD flag is set */
+ if(SPDIFRX_WaitOnFlagUntilTimeout(hspdif, SPDIFRX_FLAG_SYNCD, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Start reception */
+ __HAL_SPDIFRX_RCV(hspdif);
+
+ /* Receive data flow */
+ while(sizeCounter > 0U)
+ {
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until RXNE flag is set */
+ if(SPDIFRX_WaitOnFlagUntilTimeout(hspdif, SPDIFRX_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ (*pTmpBuf) = hspdif->Instance->DR;
+ pTmpBuf++;
+ sizeCounter--;
+ }
+
+ /* SPDIFRX ready */
+ hspdif->State = HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receives an amount of data (Control Flow) in blocking mode.
+ * @param hspdif pointer to a SPDIFRX_HandleTypeDef structure that contains
+ * the configuration information for SPDIFRX 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_SPDIFRX_ReceiveCtrlFlow(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint16_t sizeCounter = Size;
+ uint32_t *pTmpBuf = pData;
+
+ if((pData == NULL ) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if(hspdif->State == HAL_SPDIFRX_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hspdif);
+
+ hspdif->State = HAL_SPDIFRX_STATE_BUSY;
+
+ /* Start synchronization */
+ __HAL_SPDIFRX_SYNC(hspdif);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until SYNCD flag is set */
+ if(SPDIFRX_WaitOnFlagUntilTimeout(hspdif, SPDIFRX_FLAG_SYNCD, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Start reception */
+ __HAL_SPDIFRX_RCV(hspdif);
+
+ /* Receive control flow */
+ while(sizeCounter > 0U)
+ {
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until CSRNE flag is set */
+ if(SPDIFRX_WaitOnFlagUntilTimeout(hspdif, SPDIFRX_FLAG_CSRNE, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ (*pTmpBuf) = hspdif->Instance->CSR;
+ pTmpBuf++;
+ sizeCounter--;
+ }
+
+ /* SPDIFRX ready */
+ hspdif->State = HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data (Data Flow) in non-blocking mode with Interrupt
+ * @param hspdif SPDIFRX handle
+ * @param pData a 32-bit pointer to the Receive data buffer.
+ * @param Size number of data sample to be received .
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_ReceiveDataFlow_IT(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size)
+{
+ register uint32_t count = SPDIFRX_TIMEOUT_VALUE * (SystemCoreClock / 24U / 1000U);
+
+ const HAL_SPDIFRX_StateTypeDef tempState = hspdif->State;
+
+ if((tempState == HAL_SPDIFRX_STATE_READY) || (tempState == HAL_SPDIFRX_STATE_BUSY_CX))
+ {
+ if((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspdif);
+
+ hspdif->pRxBuffPtr = pData;
+ hspdif->RxXferSize = Size;
+ hspdif->RxXferCount = Size;
+
+ hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE;
+
+ /* Check if a receive process is ongoing or not */
+ hspdif->State = HAL_SPDIFRX_STATE_BUSY_RX;
+
+ /* Enable the SPDIFRX PE Error Interrupt */
+ __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_PERRIE);
+
+ /* Enable the SPDIFRX OVR Error Interrupt */
+ __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_OVRIE);
+
+ /* Enable the SPDIFRX RXNE interrupt */
+ __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_RXNE);
+
+ if((SPDIFRX->CR & SPDIFRX_CR_SPDIFEN) != SPDIFRX_STATE_RCV)
+ {
+ /* Start synchronization */
+ __HAL_SPDIFRX_SYNC(hspdif);
+
+ /* Wait until SYNCD flag is set */
+ do
+ {
+ if (count == 0U)
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE);
+
+ hspdif->State= HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_TIMEOUT;
+ }
+ count--;
+ } while (__HAL_SPDIFRX_GET_FLAG(hspdif, SPDIFRX_FLAG_SYNCD) == RESET);
+
+ /* Start reception */
+ __HAL_SPDIFRX_RCV(hspdif);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data (Control Flow) with Interrupt
+ * @param hspdif SPDIFRX handle
+ * @param pData a 32-bit pointer to the Receive data buffer.
+ * @param Size number of data sample (Control Flow) to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_ReceiveCtrlFlow_IT(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size)
+{
+ register uint32_t count = SPDIFRX_TIMEOUT_VALUE * (SystemCoreClock / 24U / 1000U);
+
+ const HAL_SPDIFRX_StateTypeDef tempState = hspdif->State;
+
+ if((tempState == HAL_SPDIFRX_STATE_READY) || (tempState == HAL_SPDIFRX_STATE_BUSY_RX))
+ {
+ if((pData == NULL ) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspdif);
+
+ hspdif->pCsBuffPtr = pData;
+ hspdif->CsXferSize = Size;
+ hspdif->CsXferCount = Size;
+
+ hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE;
+
+ /* Check if a receive process is ongoing or not */
+ hspdif->State = HAL_SPDIFRX_STATE_BUSY_CX;
+
+ /* Enable the SPDIFRX PE Error Interrupt */
+ __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_PERRIE);
+
+ /* Enable the SPDIFRX OVR Error Interrupt */
+ __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_OVRIE);
+
+ /* Enable the SPDIFRX CSRNE interrupt */
+ __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_CSRNE);
+
+ if((SPDIFRX->CR & SPDIFRX_CR_SPDIFEN) != SPDIFRX_STATE_RCV)
+ {
+ /* Start synchronization */
+ __HAL_SPDIFRX_SYNC(hspdif);
+
+ /* Wait until SYNCD flag is set */
+ do
+ {
+ if (count == 0U)
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE);
+
+ hspdif->State= HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_TIMEOUT;
+ }
+ count--;
+ } while (__HAL_SPDIFRX_GET_FLAG(hspdif, SPDIFRX_FLAG_SYNCD) == RESET);
+
+ /* Start reception */
+ __HAL_SPDIFRX_RCV(hspdif);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data (Data Flow) mode with DMA
+ * @param hspdif SPDIFRX handle
+ * @param pData a 32-bit pointer to the Receive data buffer.
+ * @param Size number of data sample to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_ReceiveDataFlow_DMA(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size)
+{
+ register uint32_t count = SPDIFRX_TIMEOUT_VALUE * (SystemCoreClock / 24U / 1000U);
+
+ const HAL_SPDIFRX_StateTypeDef tempState = hspdif->State;
+
+ if((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if((tempState == HAL_SPDIFRX_STATE_READY) || (tempState == HAL_SPDIFRX_STATE_BUSY_CX))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hspdif);
+
+ hspdif->pRxBuffPtr = pData;
+ hspdif->RxXferSize = Size;
+ hspdif->RxXferCount = Size;
+
+ hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE;
+ hspdif->State = HAL_SPDIFRX_STATE_BUSY_RX;
+
+ /* Set the SPDIFRX Rx DMA Half transfer complete callback */
+ hspdif->hdmaDrRx->XferHalfCpltCallback = SPDIFRX_DMARxHalfCplt;
+
+ /* Set the SPDIFRX Rx DMA transfer complete callback */
+ hspdif->hdmaDrRx->XferCpltCallback = SPDIFRX_DMARxCplt;
+
+ /* Set the DMA error callback */
+ hspdif->hdmaDrRx->XferErrorCallback = SPDIFRX_DMAError;
+
+ /* Enable the DMA request */
+ if(HAL_DMA_Start_IT(hspdif->hdmaDrRx, (uint32_t)&hspdif->Instance->DR, (uint32_t)hspdif->pRxBuffPtr, Size) != HAL_OK)
+ {
+ /* Set SPDIFRX error */
+ hspdif->ErrorCode = HAL_SPDIFRX_ERROR_DMA;
+
+ /* Set SPDIFRX state */
+ hspdif->State = HAL_SPDIFRX_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable RXDMAEN bit in SPDIFRX CR register for data flow reception*/
+ hspdif->Instance->CR |= SPDIFRX_CR_RXDMAEN;
+
+ if((SPDIFRX->CR & SPDIFRX_CR_SPDIFEN) != SPDIFRX_STATE_RCV)
+ {
+ /* Start synchronization */
+ __HAL_SPDIFRX_SYNC(hspdif);
+
+ /* Wait until SYNCD flag is set */
+ do
+ {
+ if (count == 0U)
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE);
+
+ hspdif->State= HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_TIMEOUT;
+ }
+ count--;
+ } while (__HAL_SPDIFRX_GET_FLAG(hspdif, SPDIFRX_FLAG_SYNCD) == RESET);
+
+ /* Start reception */
+ __HAL_SPDIFRX_RCV(hspdif);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data (Control Flow) with DMA
+ * @param hspdif SPDIFRX handle
+ * @param pData a 32-bit pointer to the Receive data buffer.
+ * @param Size number of data (Control Flow) sample to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_ReceiveCtrlFlow_DMA(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size)
+{
+ register uint32_t count = SPDIFRX_TIMEOUT_VALUE * (SystemCoreClock / 24U / 1000U);
+
+ const HAL_SPDIFRX_StateTypeDef tempState = hspdif->State;
+
+ if((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if((tempState == HAL_SPDIFRX_STATE_READY) || (tempState == HAL_SPDIFRX_STATE_BUSY_RX))
+ {
+ hspdif->pCsBuffPtr = pData;
+ hspdif->CsXferSize = Size;
+ hspdif->CsXferCount = Size;
+
+ /* Process Locked */
+ __HAL_LOCK(hspdif);
+
+ hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE;
+ hspdif->State = HAL_SPDIFRX_STATE_BUSY_CX;
+
+ /* Set the SPDIFRX Rx DMA Half transfer complete callback */
+ hspdif->hdmaCsRx->XferHalfCpltCallback = SPDIFRX_DMACxHalfCplt;
+
+ /* Set the SPDIFRX Rx DMA transfer complete callback */
+ hspdif->hdmaCsRx->XferCpltCallback = SPDIFRX_DMACxCplt;
+
+ /* Set the DMA error callback */
+ hspdif->hdmaCsRx->XferErrorCallback = SPDIFRX_DMAError;
+
+ /* Enable the DMA request */
+ if(HAL_DMA_Start_IT(hspdif->hdmaCsRx, (uint32_t)&hspdif->Instance->CSR, (uint32_t)hspdif->pCsBuffPtr, Size) != HAL_OK)
+ {
+ /* Set SPDIFRX error */
+ hspdif->ErrorCode = HAL_SPDIFRX_ERROR_DMA;
+
+ /* Set SPDIFRX state */
+ hspdif->State = HAL_SPDIFRX_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable CBDMAEN bit in SPDIFRX CR register for control flow reception*/
+ hspdif->Instance->CR |= SPDIFRX_CR_CBDMAEN;
+
+ if((SPDIFRX->CR & SPDIFRX_CR_SPDIFEN) != SPDIFRX_STATE_RCV)
+ {
+ /* Start synchronization */
+ __HAL_SPDIFRX_SYNC(hspdif);
+
+ /* Wait until SYNCD flag is set */
+ do
+ {
+ if (count == 0U)
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE);
+
+ hspdif->State= HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_TIMEOUT;
+ }
+ count--;
+ } while (__HAL_SPDIFRX_GET_FLAG(hspdif, SPDIFRX_FLAG_SYNCD) == RESET);
+
+ /* Start reception */
+ __HAL_SPDIFRX_RCV(hspdif);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief stop the audio stream receive from the Media.
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_SPDIFRX_DMAStop(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Process Locked */
+ __HAL_LOCK(hspdif);
+
+ /* Disable the SPDIFRX DMA requests */
+ hspdif->Instance->CR &= (uint16_t)(~SPDIFRX_CR_RXDMAEN);
+ hspdif->Instance->CR &= (uint16_t)(~SPDIFRX_CR_CBDMAEN);
+
+ /* Disable the SPDIFRX DMA channel */
+ __HAL_DMA_DISABLE(hspdif->hdmaDrRx);
+ __HAL_DMA_DISABLE(hspdif->hdmaCsRx);
+
+ /* Disable SPDIFRX peripheral */
+ __HAL_SPDIFRX_IDLE(hspdif);
+
+ hspdif->State = HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles SPDIFRX interrupt request.
+ * @param hspdif SPDIFRX handle
+ * @retval HAL status
+ */
+void HAL_SPDIFRX_IRQHandler(SPDIFRX_HandleTypeDef *hspdif)
+{
+ uint32_t itFlag = hspdif->Instance->SR;
+ uint32_t itSource = hspdif->Instance->IMR;
+
+ /* SPDIFRX in mode Data Flow Reception */
+ if(((itFlag & SPDIFRX_FLAG_RXNE) == SPDIFRX_FLAG_RXNE) && ((itSource & SPDIFRX_IT_RXNE) == SPDIFRX_IT_RXNE))
+ {
+ __HAL_SPDIFRX_CLEAR_IT(hspdif, SPDIFRX_IT_RXNE);
+ SPDIFRX_ReceiveDataFlow_IT(hspdif);
+ }
+
+ /* SPDIFRX in mode Control Flow Reception */
+ if(((itFlag & SPDIFRX_FLAG_CSRNE) == SPDIFRX_FLAG_CSRNE) && ((itSource & SPDIFRX_IT_CSRNE) == SPDIFRX_IT_CSRNE))
+ {
+ __HAL_SPDIFRX_CLEAR_IT(hspdif, SPDIFRX_IT_CSRNE);
+ SPDIFRX_ReceiveControlFlow_IT(hspdif);
+ }
+
+ /* SPDIFRX Overrun error interrupt occurred */
+ if(((itFlag & SPDIFRX_FLAG_OVR) == SPDIFRX_FLAG_OVR) && ((itSource & SPDIFRX_IT_OVRIE) == SPDIFRX_IT_OVRIE))
+ {
+ __HAL_SPDIFRX_CLEAR_IT(hspdif, SPDIFRX_IT_OVRIE);
+
+ /* Change the SPDIFRX error code */
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_OVR;
+
+ /* the transfer is not stopped */
+ HAL_SPDIFRX_ErrorCallback(hspdif);
+ }
+
+ /* SPDIFRX Parity error interrupt occurred */
+ if(((itFlag & SPDIFRX_FLAG_PERR) == SPDIFRX_FLAG_PERR) && ((itSource & SPDIFRX_IT_PERRIE) == SPDIFRX_IT_PERRIE))
+ {
+ __HAL_SPDIFRX_CLEAR_IT(hspdif, SPDIFRX_IT_PERRIE);
+
+ /* Change the SPDIFRX error code */
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_PE;
+
+ /* the transfer is not stopped */
+ HAL_SPDIFRX_ErrorCallback(hspdif);
+ }
+}
+
+/**
+ * @brief Rx Transfer (Data flow) half completed callbacks
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+__weak void HAL_SPDIFRX_RxHalfCpltCallback(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspdif);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SPDIFRX_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer (Data flow) completed callbacks
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+__weak void HAL_SPDIFRX_RxCpltCallback(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspdif);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SPDIFRX_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx (Control flow) Transfer half completed callbacks
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+__weak void HAL_SPDIFRX_CxHalfCpltCallback(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspdif);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SPDIFRX_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer (Control flow) completed callbacks
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+__weak void HAL_SPDIFRX_CxCpltCallback(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspdif);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SPDIFRX_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SPDIFRX error callbacks
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+__weak void HAL_SPDIFRX_ErrorCallback(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspdif);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SPDIFRX_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPDIFRX_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+===============================================================================
+##### Peripheral State and Errors functions #####
+===============================================================================
+[..]
+This subsection permit to get in run-time the status of the peripheral
+and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the SPDIFRX state
+ * @param hspdif SPDIFRX handle
+ * @retval HAL state
+ */
+HAL_SPDIFRX_StateTypeDef HAL_SPDIFRX_GetState(SPDIFRX_HandleTypeDef const * const hspdif)
+{
+ return hspdif->State;
+}
+
+/**
+ * @brief Return the SPDIFRX error code
+ * @param hspdif SPDIFRX handle
+ * @retval SPDIFRX Error Code
+ */
+uint32_t HAL_SPDIFRX_GetError(SPDIFRX_HandleTypeDef const * const hspdif)
+{
+ return hspdif->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief DMA SPDIFRX receive process (Data flow) complete callback
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SPDIFRX_DMARxCplt(DMA_HandleTypeDef *hdma)
+{
+ SPDIFRX_HandleTypeDef* hspdif = ( SPDIFRX_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Disable Rx DMA Request */
+ if(hdma->Init.Mode != DMA_CIRCULAR)
+ {
+ hspdif->Instance->CR &= (uint16_t)(~SPDIFRX_CR_RXDMAEN);
+ hspdif->RxXferCount = 0;
+ hspdif->State = HAL_SPDIFRX_STATE_READY;
+ }
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+ hspdif->RxCpltCallback(hspdif);
+#else
+ HAL_SPDIFRX_RxCpltCallback(hspdif);
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPDIFRX receive process (Data flow) half complete callback
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SPDIFRX_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ SPDIFRX_HandleTypeDef* hspdif = (SPDIFRX_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+ hspdif->RxHalfCpltCallback(hspdif);
+#else
+ HAL_SPDIFRX_RxHalfCpltCallback(hspdif);
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+}
+
+
+/**
+ * @brief DMA SPDIFRX receive process (Control flow) complete callback
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SPDIFRX_DMACxCplt(DMA_HandleTypeDef *hdma)
+{
+ SPDIFRX_HandleTypeDef* hspdif = ( SPDIFRX_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Disable Cb DMA Request */
+ hspdif->Instance->CR &= (uint16_t)(~SPDIFRX_CR_CBDMAEN);
+ hspdif->CsXferCount = 0;
+
+ hspdif->State = HAL_SPDIFRX_STATE_READY;
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+ hspdif->CxCpltCallback(hspdif);
+#else
+ HAL_SPDIFRX_CxCpltCallback(hspdif);
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPDIFRX receive process (Control flow) half complete callback
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SPDIFRX_DMACxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ SPDIFRX_HandleTypeDef* hspdif = (SPDIFRX_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+ hspdif->CxHalfCpltCallback(hspdif);
+#else
+ HAL_SPDIFRX_CxHalfCpltCallback(hspdif);
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPDIFRX communication error callback
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SPDIFRX_DMAError(DMA_HandleTypeDef *hdma)
+{
+ SPDIFRX_HandleTypeDef* hspdif = ( SPDIFRX_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Disable Rx and Cb DMA Request */
+ hspdif->Instance->CR &= (uint16_t)(~(SPDIFRX_CR_RXDMAEN | SPDIFRX_CR_CBDMAEN));
+ hspdif->RxXferCount = 0;
+
+ hspdif->State= HAL_SPDIFRX_STATE_READY;
+
+ /* Set the error code and execute error callback*/
+ hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_DMA;
+
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+ /* The transfer is not stopped */
+ hspdif->ErrorCallback(hspdif);
+#else
+ /* The transfer is not stopped */
+ HAL_SPDIFRX_ErrorCallback(hspdif);
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief Receive an amount of data (Data Flow) with Interrupt
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+static void SPDIFRX_ReceiveDataFlow_IT(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Receive data */
+ (*hspdif->pRxBuffPtr) = hspdif->Instance->DR;
+ hspdif->pRxBuffPtr++;
+ hspdif->RxXferCount--;
+
+ if(hspdif->RxXferCount == 0U)
+ {
+ /* Disable RXNE/PE and OVR interrupts */
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE | SPDIFRX_IT_PERRIE | SPDIFRX_IT_RXNE);
+
+ hspdif->State = HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+ hspdif->RxCpltCallback(hspdif);
+#else
+ HAL_SPDIFRX_RxCpltCallback(hspdif);
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Receive an amount of data (Control Flow) with Interrupt
+ * @param hspdif SPDIFRX handle
+ * @retval None
+ */
+static void SPDIFRX_ReceiveControlFlow_IT(SPDIFRX_HandleTypeDef *hspdif)
+{
+ /* Receive data */
+ (*hspdif->pCsBuffPtr) = hspdif->Instance->CSR;
+ hspdif->pCsBuffPtr++;
+ hspdif->CsXferCount--;
+
+ if(hspdif->CsXferCount == 0U)
+ {
+ /* Disable CSRNE interrupt */
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE);
+
+ hspdif->State = HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1)
+ hspdif->CxCpltCallback(hspdif);
+#else
+ HAL_SPDIFRX_CxCpltCallback(hspdif);
+#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief This function handles SPDIFRX Communication Timeout.
+ * @param hspdif SPDIFRX handle
+ * @param Flag Flag checked
+ * @param Status Value of the flag expected
+ * @param Timeout Duration of the timeout
+ * @param tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPDIFRX_WaitOnFlagUntilTimeout(SPDIFRX_HandleTypeDef *hspdif, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t tickstart)
+{
+ /* Wait until flag is set */
+ while(__HAL_SPDIFRX_GET_FLAG(hspdif, Flag) == Status)
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE);
+ __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE);
+
+ hspdif->State= HAL_SPDIFRX_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspdif);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+
+#endif /* SPDIFRX */
+#endif /* HAL_SPDIFRX_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_spi.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_spi.c
new file mode 100644
index 0000000000..0d3f32bca9
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_spi.c
@@ -0,0 +1,3836 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_spi.c
+ * @author MCD Application Team
+ * @brief SPI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Serial Peripheral Interface (SPI) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The SPI HAL driver can be used as follows:
+
+ (#) Declare a SPI_HandleTypeDef handle structure, for example:
+ SPI_HandleTypeDef hspi;
+
+ (#)Initialize the SPI low level resources by implementing the HAL_SPI_MspInit() API:
+ (##) Enable the SPIx interface clock
+ (##) SPI pins configuration
+ (+++) Enable the clock for the SPI GPIOs
+ (+++) Configure these SPI pins as alternate function push-pull
+ (##) NVIC configuration if you need to use interrupt process or DMA process
+ (+++) Configure the SPIx interrupt priority
+ (+++) Enable the NVIC SPI IRQ handle
+ (##) DMA Configuration if you need to use DMA process
+ (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive Stream/Channel
+ (+++) Enable the DMAx clock
+ (+++) Configure the DMA handle parameters
+ (+++) Configure the DMA Tx or Rx Stream/Channel
+ (+++) Associate the initialized hdma_tx handle to the hspi DMA Tx or Rx handle
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx or Rx Stream/Channel
+
+ (#) Program the Mode, BidirectionalMode , Data size, Baudrate Prescaler, NSS
+ management, Clock polarity and phase, FirstBit and CRC configuration in the hspi Init structure.
+
+ (#) Initialize the SPI registers by calling the HAL_SPI_Init() API:
+ (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
+ by calling the customized HAL_SPI_MspInit() API.
+ [..]
+ Callback registration:
+
+ (#) The compilation flag USE_HAL_SPI_REGISTER_CALLBACKS when set to 1UL
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions HAL_SPI_RegisterCallback() to register an interrupt callback.
+
+ Function HAL_SPI_RegisterCallback() allows to register following callbacks:
+ (+) TxCpltCallback : SPI Tx Completed callback
+ (+) RxCpltCallback : SPI Rx Completed callback
+ (+) TxRxCpltCallback : SPI TxRx Completed callback
+ (+) TxHalfCpltCallback : SPI Tx Half Completed callback
+ (+) RxHalfCpltCallback : SPI Rx Half Completed callback
+ (+) TxRxHalfCpltCallback : SPI TxRx Half Completed callback
+ (+) ErrorCallback : SPI Error callback
+ (+) AbortCpltCallback : SPI Abort callback
+ (+) MspInitCallback : SPI Msp Init callback
+ (+) MspDeInitCallback : SPI Msp DeInit callback
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+
+ (#) Use function HAL_SPI_UnRegisterCallback to reset a callback to the default
+ weak function.
+ HAL_SPI_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxCpltCallback : SPI Tx Completed callback
+ (+) RxCpltCallback : SPI Rx Completed callback
+ (+) TxRxCpltCallback : SPI TxRx Completed callback
+ (+) TxHalfCpltCallback : SPI Tx Half Completed callback
+ (+) RxHalfCpltCallback : SPI Rx Half Completed callback
+ (+) TxRxHalfCpltCallback : SPI TxRx Half Completed callback
+ (+) ErrorCallback : SPI Error callback
+ (+) AbortCpltCallback : SPI Abort callback
+ (+) MspInitCallback : SPI Msp Init callback
+ (+) MspDeInitCallback : SPI Msp DeInit callback
+
+ By default, after the HAL_SPI_Init() and when the state is HAL_SPI_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples HAL_SPI_MasterTxCpltCallback(), HAL_SPI_MasterRxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the HAL_SPI_Init()/ HAL_SPI_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ If MspInit or MspDeInit are not null, the HAL_SPI_Init()/ HAL_SPI_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+
+ Callbacks can be registered/unregistered in HAL_SPI_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in HAL_SPI_STATE_READY or HAL_SPI_STATE_RESET state,
+ thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
+ Then, the user first registers the MspInit/MspDeInit user callbacks
+ using HAL_SPI_RegisterCallback() before calling HAL_SPI_DeInit()
+ or HAL_SPI_Init() function.
+
+ When The compilation define USE_HAL_PPP_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+
+ [..]
+ Circular mode restriction:
+ (+) The DMA circular mode cannot be used when the SPI is configured in these modes:
+ (++) Master 2Lines RxOnly
+ (++) Master 1Line Rx
+ (+) The CRC feature is not managed when the DMA circular mode is enabled
+ (+) The functions HAL_SPI_DMAPause()/ HAL_SPI_DMAResume() are not supported. Return always
+ HAL_ERROR with ErrorCode set to HAL_SPI_ERROR_NOT_SUPPORTED.
+ Those functions are maintained for backward compatibility reasons.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SPI SPI
+ * @brief SPI HAL module driver
+ * @{
+ */
+#ifdef HAL_SPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup SPI_Private_Constants SPI Private Constants
+ * @{
+ */
+#define SPI_DEFAULT_TIMEOUT 100UL
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup SPI_Private_Functions SPI Private Functions
+ * @{
+ */
+static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAError(DMA_HandleTypeDef *hdma);
+static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma);
+static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
+static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef SPI_WaitOnFlagUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus FlagStatus,
+ uint32_t Timeout, uint32_t Tickstart);
+static void SPI_TxISR_8BIT(SPI_HandleTypeDef *hspi);
+static void SPI_TxISR_16BIT(SPI_HandleTypeDef *hspi);
+static void SPI_TxISR_32BIT(SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_8BIT(SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_16BIT(SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_32BIT(SPI_HandleTypeDef *hspi);
+static void SPI_AbortTransfer(SPI_HandleTypeDef *hspi);
+static void SPI_CloseTransfer(SPI_HandleTypeDef *hspi);
+static uint32_t SPI_GetPacketSize(SPI_HandleTypeDef *hspi);
+
+
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup SPI_Exported_Functions SPI Exported Functions
+ * @{
+ */
+
+/** @defgroup SPI_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to initialize and
+ de-initialize the SPIx peripheral:
+
+ (+) User must implement HAL_SPI_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_SPI_Init() to configure the selected device with
+ the selected configuration:
+ (++) Mode
+ (++) Direction
+ (++) Data Size
+ (++) Clock Polarity and Phase
+ (++) NSS Management
+ (++) BaudRate Prescaler
+ (++) FirstBit
+ (++) TIMode
+ (++) CRC Calculation
+ (++) CRC Polynomial if CRC enabled
+ (++) CRC Length, used only with Data8 and Data16
+ (++) FIFO reception threshold
+ (++) FIFO transmission threshold
+
+ (+) Call the function HAL_SPI_DeInit() to restore the default configuration
+ of the selected SPIx peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the SPI according to the specified parameters
+ * in the SPI_InitTypeDef and initialize the associated handle.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi)
+{
+ uint32_t crc_length = 0UL;
+ uint32_t packet_length;
+
+ /* Check the SPI handle allocation */
+ if (hspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
+ assert_param(IS_SPI_MODE(hspi->Init.Mode));
+ assert_param(IS_SPI_DIRECTION(hspi->Init.Direction));
+ assert_param(IS_SPI_DATASIZE(hspi->Init.DataSize));
+ assert_param(IS_SPI_FIFOTHRESHOLD(hspi->Init.FifoThreshold));
+ assert_param(IS_SPI_NSS(hspi->Init.NSS));
+ assert_param(IS_SPI_NSSP(hspi->Init.NSSPMode));
+ assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
+ assert_param(IS_SPI_FIRST_BIT(hspi->Init.FirstBit));
+ assert_param(IS_SPI_TIMODE(hspi->Init.TIMode));
+ if (hspi->Init.TIMode == SPI_TIMODE_DISABLE)
+ {
+ assert_param(IS_SPI_CPOL(hspi->Init.CLKPolarity));
+ assert_param(IS_SPI_CPHA(hspi->Init.CLKPhase));
+ }
+#if (USE_SPI_CRC != 0UL)
+ assert_param(IS_SPI_CRC_CALCULATION(hspi->Init.CRCCalculation));
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial));
+ assert_param(IS_SPI_CRC_LENGTH(hspi->Init.CRCLength));
+ assert_param(IS_SPI_CRC_INITIALIZATION_PATTERN(hspi->Init.TxCRCInitializationPattern));
+ assert_param(IS_SPI_CRC_INITIALIZATION_PATTERN(hspi->Init.RxCRCInitializationPattern));
+ }
+#else
+ hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+#endif /* USE_SPI_CRC */
+
+ /* Verify that the SPI instance supports Data Size higher than 16bits */
+ if ((!IS_SPI_HIGHEND_INSTANCE(hspi->Instance)) && (hspi->Init.DataSize > SPI_DATASIZE_16BIT))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Verify that the SPI instance supports requested data packing */
+ packet_length = SPI_GetPacketSize(hspi);
+ if (((!IS_SPI_HIGHEND_INSTANCE(hspi->Instance)) && (packet_length > SPI_LOWEND_FIFO_SIZE)) ||
+ ((IS_SPI_HIGHEND_INSTANCE(hspi->Instance)) && (packet_length > SPI_HIGHEND_FIFO_SIZE)))
+ {
+ return HAL_ERROR;
+ }
+
+#if (USE_SPI_CRC != 0UL)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Verify that the SPI instance supports CRC Length higher than 16bits */
+ if ((!IS_SPI_HIGHEND_INSTANCE(hspi->Instance)) && (hspi->Init.CRCLength > SPI_CRC_LENGTH_16BIT))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Align the CRC Length on the data size */
+ if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE)
+ {
+ crc_length = (hspi->Init.DataSize >> SPI_CFG1_DSIZE_Pos) << SPI_CFG1_CRCSIZE_Pos;
+ }
+ else
+ {
+ crc_length = hspi->Init.CRCLength;
+ }
+
+ /* Verify that the CRC Length is higher than DataSize */
+ if ((hspi->Init.DataSize >> SPI_CFG1_DSIZE_Pos) > (crc_length >> SPI_CFG1_CRCSIZE_Pos))
+ {
+ return HAL_ERROR;
+ }
+ }
+#endif /* USE_SPI_CRC */
+
+ if (hspi->State == HAL_SPI_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hspi->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ /* Init the SPI Callback settings */
+ hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
+ hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
+ hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */
+ hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+
+ if (hspi->MspInitCallback == NULL)
+ {
+ hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ hspi->MspInitCallback(hspi);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ HAL_SPI_MspInit(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+
+ hspi->State = HAL_SPI_STATE_BUSY;
+
+ /* Disable the selected SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/
+ /* Configure : SPI Mode, Communication Mode, Clock polarity and phase, NSS management,
+ Communication speed, First bit, CRC calculation state, CRC Length */
+
+ if ((hspi->Init.NSS == SPI_NSS_SOFT) && (hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.NSSPolarity == SPI_NSS_POLARITY_LOW))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_SSI);
+ }
+
+ /* SPIx CFG1 Configuration */
+ WRITE_REG(hspi->Instance->CFG1, (hspi->Init.BaudRatePrescaler | hspi->Init.CRCCalculation | crc_length |
+ hspi->Init.FifoThreshold | hspi->Init.DataSize));
+
+ /* SPIx CFG2 Configuration */
+ WRITE_REG(hspi->Instance->CFG2, (hspi->Init.NSSPMode | hspi->Init.TIMode | hspi->Init.NSSPolarity |
+ hspi->Init.NSS | hspi->Init.CLKPolarity | hspi->Init.CLKPhase |
+ hspi->Init.FirstBit | hspi->Init.Mode | hspi->Init.MasterInterDataIdleness |
+ hspi->Init.Direction | hspi->Init.MasterSSIdleness | hspi->Init.IOSwap));
+
+#if (USE_SPI_CRC != 0UL)
+ /*---------------------------- SPIx CRCPOLY Configuration ------------------*/
+ /* Configure : CRC Polynomial */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Initialize TXCRC Pattern Initial Value */
+ if (hspi->Init.TxCRCInitializationPattern == SPI_CRC_INITIALIZATION_ALL_ONE_PATTERN)
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_TCRCINI);
+ }
+ else
+ {
+ CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_TCRCINI);
+ }
+
+ /* Initialize RXCRC Pattern Initial Value */
+ if (hspi->Init.RxCRCInitializationPattern == SPI_CRC_INITIALIZATION_ALL_ONE_PATTERN)
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_RCRCINI);
+ }
+ else
+ {
+ CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_RCRCINI);
+ }
+
+ /* Enable 33/17 bits CRC computation */
+ if (((!IS_SPI_HIGHEND_INSTANCE(hspi->Instance)) && (crc_length == SPI_CRC_LENGTH_16BIT)) ||
+ ((IS_SPI_HIGHEND_INSTANCE(hspi->Instance)) && (crc_length == SPI_CRC_LENGTH_32BIT)))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRC33_17);
+ }
+ else
+ {
+ CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRC33_17);
+ }
+
+ /* Write CRC polynomial in SPI Register */
+ WRITE_REG(hspi->Instance->CRCPOLY, hspi->Init.CRCPolynomial);
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Insure that Underrun configuration is managed only by Salve */
+ if (hspi->Init.Mode == SPI_MODE_SLAVE)
+ {
+ /* Set Default Underrun configuration */
+#if (USE_SPI_CRC != 0UL)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_DISABLE)
+#endif
+ {
+ MODIFY_REG(hspi->Instance->CFG1, SPI_CFG1_UDRDET, SPI_CFG1_UDRDET_0);
+ }
+ MODIFY_REG(hspi->Instance->CFG1, SPI_CFG1_UDRCFG, SPI_CFG1_UDRCFG_1);
+ }
+
+#if defined(SPI_I2SCFGR_I2SMOD)
+ /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */
+ CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD);
+#endif /* SPI_I2SCFGR_I2SMOD */
+
+ /* Insure that AFCNTR is managed only by Master */
+ if ((hspi->Init.Mode & SPI_MODE_MASTER) == SPI_MODE_MASTER)
+ {
+ /* Alternate function GPIOs control */
+ MODIFY_REG(hspi->Instance->CFG2, SPI_CFG2_AFCNTR, (hspi->Init.MasterKeepIOState));
+ }
+
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->State = HAL_SPI_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief De-Initialize the SPI peripheral.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi)
+{
+ /* Check the SPI handle allocation */
+ if (hspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check SPI Instance parameter */
+ assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
+
+ hspi->State = HAL_SPI_STATE_BUSY;
+
+ /* Disable the SPI Peripheral Clock */
+ __HAL_SPI_DISABLE(hspi);
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ if (hspi->MspDeInitCallback == NULL)
+ {
+ hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ hspi->MspDeInitCallback(hspi);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ HAL_SPI_MspDeInit(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->State = HAL_SPI_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the SPI MSP.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_MspInit should be implemented in the user file
+ */
+}
+
+/**
+ * @brief De-Initialize the SPI MSP.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_MspDeInit should be implemented in the user file
+ */
+}
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+/**
+ * @brief Register a User SPI Callback
+ * To be used instead of the weak predefined callback
+ * @param hspi Pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI.
+ * @param CallbackID ID of the callback to be registered
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID, pSPI_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hspi->ErrorCode |= HAL_SPI_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ if (HAL_SPI_STATE_READY == hspi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPI_TX_COMPLETE_CB_ID :
+ hspi->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_RX_COMPLETE_CB_ID :
+ hspi->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_TX_RX_COMPLETE_CB_ID :
+ hspi->TxRxCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
+ hspi->TxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
+ hspi->RxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
+ hspi->TxRxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_ERROR_CB_ID :
+ hspi->ErrorCallback = pCallback;
+ break;
+
+ case HAL_SPI_ABORT_CB_ID :
+ hspi->AbortCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_MSPINIT_CB_ID :
+ hspi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SPI_MSPDEINIT_CB_ID :
+ hspi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_SPI_STATE_RESET == hspi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPI_MSPINIT_CB_ID :
+ hspi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SPI_MSPDEINIT_CB_ID :
+ hspi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hspi);
+ return status;
+}
+
+/**
+ * @brief Unregister an SPI Callback
+ * SPI callback is redirected to the weak predefined callback
+ * @param hspi Pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI.
+ * @param CallbackID ID of the callback to be unregistered
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ if (HAL_SPI_STATE_READY == hspi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPI_TX_COMPLETE_CB_ID :
+ hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ break;
+
+ case HAL_SPI_RX_COMPLETE_CB_ID :
+ hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ break;
+
+ case HAL_SPI_TX_RX_COMPLETE_CB_ID :
+ hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
+ break;
+
+ case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
+ hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ break;
+
+ case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
+ hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ break;
+
+ case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
+ hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
+ break;
+
+ case HAL_SPI_ERROR_CB_ID :
+ hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_SPI_ABORT_CB_ID :
+ hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ break;
+
+ case HAL_SPI_MSPINIT_CB_ID :
+ hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_SPI_MSPDEINIT_CB_ID :
+ hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_SPI_STATE_RESET == hspi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPI_MSPINIT_CB_ID :
+ hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_SPI_MSPDEINIT_CB_ID :
+ hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hspi);
+ return status;
+}
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Exported_Functions_Group2 IO operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the SPI
+ data transfers.
+
+ [..] The SPI supports master and slave mode :
+
+ (#) There are two modes of transfer:
+ (##) Blocking mode: The communication is performed in polling mode.
+ The HAL status of all data processing is returned by the same function
+ after finishing transfer.
+ (##) No-Blocking mode: The communication is performed using Interrupts
+ or DMA, These APIs return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated SPI IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+ The HAL_SPI_TxCpltCallback(), HAL_SPI_RxCpltCallback() and HAL_SPI_TxRxCpltCallback() user callbacks
+ will be executed respectively at the end of the transmit or Receive process
+ The HAL_SPI_ErrorCallback()user callback will be executed when a communication error is detected
+
+ (#) APIs provided for these 2 transfer modes (Blocking mode or Non blocking mode using either Interrupt or DMA)
+ exist for 1Line (simplex) and 2Lines (full duplex) modes.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmit an amount of data in blocking mode.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData : pointer to data buffer
+ * @param Size : amount of data to be sent
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+#if defined (__GNUC__)
+ __IO uint16_t *ptxdr_16bits = (__IO uint16_t *)(&(hspi->Instance->TXDR));
+#endif /* __GNUC__ */
+
+ uint32_t tickstart;
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE_2LINES_TXONLY(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (uint8_t *)pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+
+ /*Init field not used in handle to zero */
+ hspi->pRxBuffPtr = NULL;
+ hspi->RxXferSize = (uint16_t) 0UL;
+ hspi->RxXferCount = (uint16_t) 0UL;
+ hspi->TxISR = NULL;
+ hspi->RxISR = NULL;
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_TX(hspi);
+ }
+
+ /* Set the number of data at current transfer */
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ /* Master transfer start */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
+ }
+
+ /* Transmit data in 32 Bit mode */
+ if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
+ {
+ /* Transmit data in 32 Bit mode */
+ while (hspi->TxXferCount > 0UL)
+ {
+ /* Wait until TXP flag is set to send data */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP))
+ {
+ *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint32_t);
+ hspi->TxXferCount--;
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+ /* Transmit data in 16 Bit mode */
+ else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* Transmit data in 16 Bit mode */
+ while (hspi->TxXferCount > 0UL)
+ {
+ /* Wait until TXP flag is set to send data */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP))
+ {
+ if ((hspi->TxXferCount > 1UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
+ {
+ *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint32_t);
+ hspi->TxXferCount -= (uint16_t)2UL;
+ }
+ else
+ {
+#if defined (__GNUC__)
+ *ptxdr_16bits = *((uint16_t *)hspi->pTxBuffPtr);
+#else
+ *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
+#endif /* __GNUC__ */
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+ }
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+ /* Transmit data in 8 Bit mode */
+ else
+ {
+ while (hspi->TxXferCount > 0UL)
+ {
+ /* Wait until TXP flag is set to send data */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP))
+ {
+ if ((hspi->TxXferCount > 3UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_03DATA))
+ {
+ *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint32_t);
+ hspi->TxXferCount -= (uint16_t)4UL;
+ }
+ else if ((hspi->TxXferCount > 1UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
+ {
+#if defined (__GNUC__)
+ *ptxdr_16bits = *((uint16_t *)hspi->pTxBuffPtr);
+#else
+ *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
+#endif /* __GNUC__ */
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= (uint16_t)2UL;
+ }
+ else
+ {
+ *((__IO uint8_t *)&hspi->Instance->TXDR) = *((uint8_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint8_t);
+ hspi->TxXferCount--;
+ }
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Wait for Tx (and CRC) data to be sent */
+ if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_EOT, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ }
+
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ hspi->State = HAL_SPI_STATE_READY;
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ return errorcode;
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData : pointer to data buffer
+ * @param Size : amount of data to be received
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef errorcode = HAL_OK;
+#if defined (__GNUC__)
+ __IO uint16_t *prxdr_16bits = (__IO uint16_t *)(&(hspi->Instance->RXDR));
+#endif /* __GNUC__ */
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE_2LINES_RXONLY(hspi->Init.Direction));
+
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
+ return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout);
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = (uint8_t *)pData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /*Init field not used in handle to zero */
+ hspi->pTxBuffPtr = NULL;
+ hspi->TxXferSize = (uint16_t) 0UL;
+ hspi->TxXferCount = (uint16_t) 0UL;
+ hspi->RxISR = NULL;
+ hspi->TxISR = NULL;
+
+ /* Configure communication direction: 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_RX(hspi);
+ }
+
+ /* Set the number of data at current transfer */
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ /* Master transfer start */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
+ }
+
+ /* Receive data in 32 Bit mode */
+ if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
+ {
+ /* Transfer loop */
+ while (hspi->RxXferCount > 0UL)
+ {
+ /* Check the RXWNE/EOT flag */
+ if ((hspi->Instance->SR & (SPI_FLAG_RXWNE | SPI_FLAG_EOT)) != 0UL)
+ {
+ *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint32_t);
+ hspi->RxXferCount--;
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+ /* Receive data in 16 Bit mode */
+ else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* Transfer loop */
+ while (hspi->RxXferCount > 0UL)
+ {
+ /* Check the RXWNE/FRLVL flag */
+ if ((hspi->Instance->SR & (SPI_FLAG_RXWNE | SPI_FLAG_FRLVL)) != 0UL)
+ {
+ if ((hspi->Instance->SR & SPI_FLAG_RXWNE) != 0UL)
+ {
+ *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint32_t);
+ hspi->RxXferCount -= (uint16_t)2UL;
+ }
+ else
+ {
+#if defined (__GNUC__)
+ *((uint16_t *)hspi->pRxBuffPtr) = *prxdr_16bits;
+#else
+ *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
+#endif /* __GNUC__ */
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+ }
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+ /* Receive data in 8 Bit mode */
+ else
+ {
+ /* Transfer loop */
+ while (hspi->RxXferCount > 0UL)
+ {
+ /* Check the RXWNE/FRLVL flag */
+ if ((hspi->Instance->SR & (SPI_FLAG_RXWNE | SPI_FLAG_FRLVL)) != 0UL)
+ {
+ if ((hspi->Instance->SR & SPI_FLAG_RXWNE) != 0UL)
+ {
+ *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint32_t);
+ hspi->RxXferCount -= (uint16_t)4UL;
+ }
+ else if ((hspi->Instance->SR & SPI_FLAG_FRLVL) > SPI_RX_FIFO_1PACKET)
+ {
+#if defined (__GNUC__)
+ *((uint16_t *)hspi->pRxBuffPtr) = *prxdr_16bits;
+#else
+ *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
+#endif /* __GNUC__ */
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount -= (uint16_t)2UL;
+ }
+ else
+ {
+ *((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint8_t);
+ hspi->RxXferCount--;
+ }
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+
+#if (USE_SPI_CRC != 0UL)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Wait for crc data to be received */
+ if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_EOT, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ }
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ hspi->State = HAL_SPI_STATE_READY;
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ return errorcode;
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in blocking mode.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData: pointer to transmission data buffer
+ * @param pRxData: pointer to reception data buffer
+ * @param Size : amount of data to be sent and received
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,
+ uint32_t Timeout)
+{
+ HAL_SPI_StateTypeDef tmp_state;
+ HAL_StatusTypeDef errorcode = HAL_OK;
+#if defined (__GNUC__)
+ __IO uint16_t *ptxdr_16bits = (__IO uint16_t *)(&(hspi->Instance->TXDR));
+ __IO uint16_t *prxdr_16bits = (__IO uint16_t *)(&(hspi->Instance->RXDR));
+#endif /* __GNUC__ */
+
+ uint32_t tickstart;
+ uint32_t tmp_mode;
+ uint16_t initial_TxXferCount;
+ uint16_t initial_RxXferCount;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ initial_TxXferCount = Size;
+ initial_RxXferCount = Size;
+ tmp_state = hspi->State;
+ tmp_mode = hspi->Init.Mode;
+
+ if (!((tmp_state == HAL_SPI_STATE_READY) || \
+ ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp_state == HAL_SPI_STATE_BUSY_RX))))
+ {
+ errorcode = HAL_BUSY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
+ if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ }
+
+ /* Set the transaction information */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = (uint8_t *)pRxData;
+ hspi->RxXferCount = Size;
+ hspi->RxXferSize = Size;
+ hspi->pTxBuffPtr = (uint8_t *)pTxData;
+ hspi->TxXferCount = Size;
+ hspi->TxXferSize = Size;
+
+ /*Init field not used in handle to zero */
+ hspi->RxISR = NULL;
+ hspi->TxISR = NULL;
+
+ /* Set the number of data at current transfer */
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
+
+ __HAL_SPI_ENABLE(hspi);
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ /* Master transfer start */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
+ }
+
+ /* Transmit and Receive data in 32 Bit mode */
+ if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
+ {
+ while ((initial_TxXferCount > 0UL) || (initial_RxXferCount > 0UL))
+ {
+ /* Check TXP flag */
+ if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP)) && (initial_TxXferCount > 0UL))
+ {
+ *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint32_t);
+ hspi->TxXferCount --;
+ initial_TxXferCount = hspi->TxXferCount;
+ }
+
+ /* Check RXWNE/EOT flag */
+ if (((hspi->Instance->SR & (SPI_FLAG_RXWNE | SPI_FLAG_EOT)) != 0UL) && (initial_RxXferCount > 0UL))
+ {
+ *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint32_t);
+ hspi->RxXferCount --;
+ initial_RxXferCount = hspi->RxXferCount;
+ }
+ }
+
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ /* Transmit and Receive data in 16 Bit mode */
+ else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ while ((initial_TxXferCount > 0UL) || (initial_RxXferCount > 0UL))
+ {
+ /* Check TXP flag */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP) && (initial_TxXferCount > 0UL))
+ {
+ if ((initial_TxXferCount > 1UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
+ {
+ *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint32_t);
+ hspi->TxXferCount -= (uint16_t)2UL;
+ initial_TxXferCount = hspi->TxXferCount;
+ }
+ else
+ {
+#if defined (__GNUC__)
+ *ptxdr_16bits = *((uint16_t *)hspi->pTxBuffPtr);
+#else
+ *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
+#endif /* __GNUC__ */
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+ initial_TxXferCount = hspi->TxXferCount;
+ }
+ }
+
+ /* Check RXWNE/FRLVL flag */
+ if (((hspi->Instance->SR & (SPI_FLAG_RXWNE | SPI_FLAG_FRLVL)) != 0UL) && (initial_RxXferCount > 0UL))
+ {
+ if ((hspi->Instance->SR & SPI_FLAG_RXWNE) != 0UL)
+ {
+ *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint32_t);
+ hspi->RxXferCount -= (uint16_t)2UL;
+ initial_RxXferCount = hspi->RxXferCount;
+ }
+ else
+ {
+#if defined (__GNUC__)
+ *((uint16_t *)hspi->pRxBuffPtr) = *prxdr_16bits;
+#else
+ *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
+#endif /* __GNUC__ */
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+ initial_RxXferCount = hspi->RxXferCount;
+ }
+ }
+
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ }
+ /* Transmit and Receive data in 8 Bit mode */
+ else
+ {
+ while ((initial_TxXferCount > 0UL) || (initial_RxXferCount > 0UL))
+ {
+ /* check TXP flag */
+ if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP)) && (initial_TxXferCount > 0UL))
+ {
+ if ((initial_TxXferCount > 3UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_03DATA))
+ {
+ *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint32_t);
+ hspi->TxXferCount -= (uint16_t)4UL;
+ initial_TxXferCount = hspi->TxXferCount;
+ }
+ else if ((initial_TxXferCount > 1UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
+ {
+#if defined (__GNUC__)
+ *ptxdr_16bits = *((uint16_t *)hspi->pTxBuffPtr);
+#else
+ *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
+#endif /* __GNUC__ */
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= (uint16_t)2UL;
+ initial_TxXferCount = hspi->TxXferCount;
+ }
+ else
+ {
+ *((__IO uint8_t *)&hspi->Instance->TXDR) = *((uint8_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint8_t);
+ hspi->TxXferCount--;
+ initial_TxXferCount = hspi->TxXferCount;
+ }
+ }
+
+ /* Wait until RXWNE/FRLVL flag is reset */
+ if (((hspi->Instance->SR & (SPI_FLAG_RXWNE | SPI_FLAG_FRLVL)) != 0UL) && (initial_RxXferCount > 0UL))
+ {
+ if ((hspi->Instance->SR & SPI_FLAG_RXWNE) != 0UL)
+ {
+ *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint32_t);
+ hspi->RxXferCount -= (uint16_t)4UL;
+ initial_RxXferCount = hspi->RxXferCount;
+ }
+ else if ((hspi->Instance->SR & SPI_FLAG_FRLVL) > SPI_RX_FIFO_1PACKET)
+ {
+#if defined (__GNUC__)
+ *((uint16_t *)hspi->pRxBuffPtr) = *prxdr_16bits;
+#else
+ *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
+#endif /* __GNUC__ */
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount -= (uint16_t)2UL;
+ initial_RxXferCount = hspi->RxXferCount;
+ }
+ else
+ {
+ *((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint8_t);
+ hspi->RxXferCount--;
+ initial_RxXferCount = hspi->RxXferCount;
+ }
+ }
+
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Wait for Tx/Rx (and CRC) data to be sent/received */
+ if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_EOT, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ }
+
+ /* Call standard close procedure with error check */
+ SPI_CloseTransfer(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ hspi->State = HAL_SPI_STATE_READY;
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ return errorcode;
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with Interrupt.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size : amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE_2LINES_TXONLY(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (uint8_t *)pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hspi->pRxBuffPtr = NULL;
+ hspi->RxXferSize = (uint16_t) 0UL;
+ hspi->RxXferCount = (uint16_t) 0UL;
+ hspi->RxISR = NULL;
+
+ /* Set the function for IT treatment */
+ if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
+ {
+ hspi->TxISR = SPI_TxISR_32BIT;
+ }
+ else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ hspi->TxISR = SPI_TxISR_16BIT;
+ }
+ else
+ {
+ hspi->TxISR = SPI_TxISR_8BIT;
+ }
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_TX(hspi);
+ }
+
+ /* Set the number of data at current transfer */
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+
+ /* Enable EOT, TXP, FRE, MODF, UDR and TSERF interrupts */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_EOT | SPI_IT_TXP | SPI_IT_UDR | SPI_IT_FRE | SPI_IT_MODF | SPI_IT_TSERF));
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ /* Master transfer start */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
+ }
+
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with Interrupt.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size : amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE_2LINES_RXONLY(hspi->Init.Direction));
+
+ if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
+ return HAL_SPI_TransmitReceive_IT(hspi, pData, pData, Size);
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = (uint8_t *)pData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hspi->pTxBuffPtr = NULL;
+ hspi->TxXferSize = (uint16_t) 0UL;
+ hspi->TxXferCount = (uint16_t) 0UL;
+ hspi->TxISR = NULL;
+
+ /* Set the function for IT treatment */
+ if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
+ {
+ hspi->RxISR = SPI_RxISR_32BIT;
+ }
+ else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ hspi->RxISR = SPI_RxISR_16BIT;
+ }
+ else
+ {
+ hspi->RxISR = SPI_RxISR_8BIT;
+ }
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_RX(hspi);
+ }
+
+ /* Note : The SPI must be enabled after unlocking current process
+ to avoid the risk of SPI interrupt handle execution before current
+ process unlock */
+
+ /* Set the number of data at current transfer */
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+
+ /* Enable EOT, RXP, OVR, FRE, MODF and TSERF interrupts */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_EOT | SPI_IT_RXP | SPI_IT_OVR | SPI_IT_FRE | SPI_IT_MODF | SPI_IT_TSERF));
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ /* Master transfer start */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in non-blocking mode with Interrupt.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData: pointer to transmission data buffer
+ * @param pRxData: pointer to reception data buffer
+ * @param Size : amount of data to be sent and received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
+{
+ HAL_SPI_StateTypeDef tmp_state;
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ uint32_t tmp_mode;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ /* Init temporary variables */
+ tmp_state = hspi->State;
+ tmp_mode = hspi->Init.Mode;
+
+ if (!((tmp_state == HAL_SPI_STATE_READY) || \
+ ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp_state == HAL_SPI_STATE_BUSY_RX))))
+ {
+ errorcode = HAL_BUSY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
+ if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ }
+
+ /* Set the transaction information */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (uint8_t *)pTxData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = (uint8_t *)pRxData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /* Set the function for IT treatment */
+ if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
+ {
+ hspi->TxISR = SPI_TxISR_32BIT;
+ hspi->RxISR = SPI_RxISR_32BIT;
+ }
+ else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ hspi->RxISR = SPI_RxISR_16BIT;
+ hspi->TxISR = SPI_TxISR_16BIT;
+ }
+ else
+ {
+ hspi->RxISR = SPI_RxISR_8BIT;
+ hspi->TxISR = SPI_TxISR_8BIT;
+ }
+
+ /* Set the number of data at current transfer */
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+
+ /* Enable EOT, RXP, TXP, DXP, UDR, OVR, FRE, MODF and TSERF interrupts */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_EOT | SPI_IT_RXP | SPI_IT_TXP | SPI_IT_DXP | SPI_IT_UDR | SPI_IT_OVR | SPI_IT_FRE | SPI_IT_MODF | SPI_IT_TSERF));
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ /* Master transfer start */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+#if defined(USE_SPI_RELOAD_TRANSFER)
+/**
+ * @brief Transmit an additional amount of data in blocking mode.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size : amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Reload_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+ HAL_SPI_StateTypeDef tmp_state;
+
+ /* Lock the process */
+ __HAL_LOCK(hspi);
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if (hspi->State == HAL_SPI_STATE_BUSY_TX)
+ {
+ /* check if there is already a request to reload */
+ if (hspi->Reload.Requested == 1UL)
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Insert the new number of data to be sent just after the current one */
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSER, (Size & 0xFFFFFFFFUL) << 16UL);
+
+ /* Set the transaction information */
+ hspi->Reload.Requested = 1UL;
+ hspi->Reload.pTxBuffPtr = (uint8_t *)pData;
+ hspi->Reload.TxXferSize = Size;
+
+ tmp_state = hspi->State;
+
+ /* Check if the current transmit is already completed */
+ if (((hspi->Instance->CR2 & SPI_CR2_TSER) != 0UL) && (tmp_state == HAL_SPI_STATE_READY))
+ {
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TSERF);
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSER, 0UL);
+ hspi->Reload.Requested = 0UL;
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+ }
+ else
+ {
+ errorcode = HAL_ERROR;
+ return errorcode;
+ }
+
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+
+#if defined(USE_SPI_RELOAD_TRANSFER)
+/**
+ * @brief Receive an additional amount of data in blocking mode.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size : amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Reload_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+ HAL_SPI_StateTypeDef tmp_state;
+
+ /* Lock the process */
+ __HAL_LOCK(hspi);
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if (hspi->State == HAL_SPI_STATE_BUSY_RX)
+ {
+ /* check if there is already a request to reload */
+ if (hspi->Reload.Requested == 1UL)
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Insert the new number of data that will be received just after the current one */
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSER, (Size & 0xFFFFFFFFUL) << 16UL);
+
+ /* Set the transaction information */
+ hspi->Reload.Requested = 1UL;
+ hspi->Reload.pRxBuffPtr = (uint8_t *)pData;
+ hspi->Reload.RxXferSize = Size;
+
+ tmp_state = hspi->State;
+
+ /* Check if the current reception is already completed */
+ if (((hspi->Instance->CR2 & SPI_CR2_TSER) != 0UL) && (tmp_state == HAL_SPI_STATE_READY))
+ {
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TSERF);
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSER, 0UL);
+ hspi->Reload.Requested = 0UL;
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+ }
+ else
+ {
+ errorcode = HAL_ERROR;
+ return errorcode;
+ }
+
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+
+#if defined(USE_SPI_RELOAD_TRANSFER)
+/**
+ * @brief Transmit and receive an additional amount of data in blocking mode.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData: pointer to transmission data buffer
+ * @param pRxData: pointer to reception data buffer
+ * @param Size : amount of data to be sent and received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Reload_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+ HAL_SPI_StateTypeDef tmp_state;
+
+ /* Lock the process */
+ __HAL_LOCK(hspi);
+
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if (hspi->State == HAL_SPI_STATE_BUSY_TX_RX)
+ {
+ /* check if there is already a request to reload */
+ if (hspi->Reload.Requested == 1UL)
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Insert the new number of data that will be sent and received just after the current one */
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSER, (Size & 0xFFFFFFFFUL) << 16UL);
+
+ /* Set the transaction information */
+ hspi->Reload.Requested = 1UL;
+ hspi->Reload.pTxBuffPtr = (uint8_t *)pTxData;
+ hspi->Reload.TxXferSize = Size;
+ hspi->Reload.pRxBuffPtr = (uint8_t *)pRxData;
+ hspi->Reload.RxXferSize = Size;
+
+ tmp_state = hspi->State;
+
+ /* Check if the current transmit is already completed */
+ if (((hspi->Instance->CR2 & SPI_CR2_TSER) != 0UL) && (tmp_state == HAL_SPI_STATE_READY))
+ {
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TSERF);
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSER, 0UL);
+ hspi->Reload.Requested = 0UL;
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+ }
+ else
+ {
+ errorcode = HAL_ERROR;
+ return errorcode;
+ }
+
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with DMA.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size : amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE_2LINES_TXONLY(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (uint8_t *)pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hspi->pRxBuffPtr = NULL;
+ hspi->TxISR = NULL;
+ hspi->RxISR = NULL;
+ hspi->RxXferSize = (uint16_t)0UL;
+ hspi->RxXferCount = (uint16_t)0UL;
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_TX(hspi);
+ }
+
+ /* Packing mode management is enabled by the DMA settings */
+ if (((hspi->Init.DataSize > SPI_DATASIZE_16BIT) && (hspi->hdmatx->Init.MemDataAlignment != DMA_MDATAALIGN_WORD)) || \
+ ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) && ((hspi->hdmatx->Init.MemDataAlignment != DMA_MDATAALIGN_HALFWORD) && \
+ (hspi->hdmatx->Init.MemDataAlignment != DMA_MDATAALIGN_WORD))))
+ {
+ /* Restriction the DMA data received is not allowed in this mode */
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Adjust XferCount according to DMA alignment / Data size */
+ if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
+ {
+ if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 1UL) >> 1UL;
+ }
+ if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
+ {
+ hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 3UL) >> 2UL;
+ }
+ }
+ else if (hspi->Init.DataSize <= SPI_DATASIZE_16BIT)
+ {
+ if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
+ {
+ hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 1UL) >> 1UL;
+ }
+ }
+ else
+ {
+ /* Adjustment done */
+ }
+
+ /* Set the SPI TxDMA Half transfer complete callback */
+ hspi->hdmatx->XferHalfCpltCallback = SPI_DMAHalfTransmitCplt;
+
+ /* Set the SPI TxDMA transfer complete callback */
+ hspi->hdmatx->XferCpltCallback = SPI_DMATransmitCplt;
+
+ /* Set the DMA error callback */
+ hspi->hdmatx->XferErrorCallback = SPI_DMAError;
+
+ /* Set the DMA AbortCpltCallback */
+ hspi->hdmatx->XferAbortCallback = NULL;
+
+ /* Clear TXDMAEN bit*/
+ CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN);
+
+ /* Enable the Tx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->TXDR, hspi->TxXferCount))
+ {
+ /* Update SPI error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ hspi->State = HAL_SPI_STATE_READY;
+ return errorcode;
+ }
+
+ /* Set the number of data at current transfer */
+ if (hspi->hdmatx->Init.Mode == DMA_CIRCULAR)
+ {
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, 0UL);
+ }
+ else
+ {
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
+ }
+
+ /* Enable Tx DMA Request */
+ SET_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN);
+
+ /* Enable the SPI Error Interrupt Bit */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_UDR | SPI_IT_FRE | SPI_IT_MODF));
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ /* Master transfer start */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size : amount of data to be sent
+ * @note When the CRC feature is enabled the pData Length must be Size + 1.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE_2LINES_RXONLY(hspi->Init.Direction));
+
+ if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
+ return HAL_SPI_TransmitReceive_DMA(hspi, pData, pData, Size);
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if ((pData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = (uint8_t *)pData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /*Init field not used in handle to zero */
+ hspi->RxISR = NULL;
+ hspi->TxISR = NULL;
+ hspi->TxXferSize = (uint16_t) 0UL;
+ hspi->TxXferCount = (uint16_t) 0UL;
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_RX(hspi);
+ }
+
+ /* Packing mode management is enabled by the DMA settings */
+ if (((hspi->Init.DataSize > SPI_DATASIZE_16BIT) && (hspi->hdmarx->Init.MemDataAlignment != DMA_MDATAALIGN_WORD)) || \
+ ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) && ((hspi->hdmarx->Init.MemDataAlignment != DMA_MDATAALIGN_HALFWORD) && \
+ (hspi->hdmarx->Init.MemDataAlignment != DMA_MDATAALIGN_WORD))))
+ {
+ /* Restriction the DMA data received is not allowed in this mode */
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Clear RXDMAEN bit */
+ CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_RXDMAEN);
+
+ /* Adjust XferCount according to DMA alignment / Data size */
+ if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
+ {
+ if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ hspi->RxXferCount = (hspi->RxXferCount + (uint16_t) 1UL) >> 1UL;
+ }
+ if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
+ {
+ hspi->RxXferCount = (hspi->RxXferCount + (uint16_t) 3UL) >> 2UL;
+ }
+ }
+ else if (hspi->Init.DataSize <= SPI_DATASIZE_16BIT)
+ {
+ if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
+ {
+ hspi->RxXferCount = (hspi->RxXferCount + (uint16_t) 1UL) >> 1UL;
+ }
+ }
+ else
+ {
+ /* Adjustment done */
+ }
+
+ /* Set the SPI RxDMA Half transfer complete callback */
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
+
+ /* Set the SPI Rx DMA transfer complete callback */
+ hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
+
+ /* Set the DMA error callback */
+ hspi->hdmarx->XferErrorCallback = SPI_DMAError;
+
+ /* Set the DMA AbortCpltCallback */
+ hspi->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the Rx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->RXDR, (uint32_t)hspi->pRxBuffPtr, hspi->RxXferCount))
+ {
+ /* Update SPI error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ hspi->State = HAL_SPI_STATE_READY;
+ return errorcode;
+ }
+
+ /* Set the number of data at current transfer */
+ if (hspi->hdmarx->Init.Mode == DMA_CIRCULAR)
+ {
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, 0UL);
+ }
+ else
+ {
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
+ }
+
+ /* Enable Rx DMA Request */
+ SET_BIT(hspi->Instance->CFG1, SPI_CFG1_RXDMAEN);
+
+ /* Enable the SPI Error Interrupt Bit */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_OVR | SPI_IT_FRE | SPI_IT_MODF));
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ /* Master transfer start */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in non-blocking mode with DMA.
+ * @param hspi : pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData: pointer to transmission data buffer
+ * @param pRxData: pointer to reception data buffer
+ * @param Size : amount of data to be sent
+ * @note When the CRC feature is enabled the pRxData Length must be Size + 1
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData,
+ uint16_t Size)
+{
+ HAL_SPI_StateTypeDef tmp_state;
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ uint32_t tmp_mode;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ /* Init temporary variables */
+ tmp_state = hspi->State;
+ tmp_mode = hspi->Init.Mode;
+
+ if (!(((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp_state == HAL_SPI_STATE_BUSY_RX)) || (tmp_state == HAL_SPI_STATE_READY)))
+ {
+ errorcode = HAL_BUSY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0UL))
+ {
+ errorcode = HAL_ERROR;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
+ if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ }
+
+ /* Set the transaction information */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (uint8_t *)pTxData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = (uint8_t *)pRxData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hspi->RxISR = NULL;
+ hspi->TxISR = NULL;
+
+ /* Reset the Tx/Rx DMA bits */
+ CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);
+
+ /* Packing mode management is enabled by the DMA settings */
+ if (((hspi->Init.DataSize > SPI_DATASIZE_16BIT) && (hspi->hdmarx->Init.MemDataAlignment != DMA_MDATAALIGN_WORD)) || \
+ ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) && ((hspi->hdmarx->Init.MemDataAlignment != DMA_MDATAALIGN_HALFWORD) && \
+ (hspi->hdmarx->Init.MemDataAlignment != DMA_MDATAALIGN_WORD))))
+ {
+ /* Restriction the DMA data received is not allowed in this mode */
+ errorcode = HAL_ERROR;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Adjust XferCount according to DMA alignment / Data size */
+ if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
+ {
+ if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 1UL) >> 1UL;
+ }
+ if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
+ {
+ hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 3UL) >> 2UL;
+ }
+ if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ hspi->RxXferCount = (hspi->RxXferCount + (uint16_t) 1UL) >> 1UL;
+ }
+ if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
+ {
+ hspi->RxXferCount = (hspi->RxXferCount + (uint16_t) 3UL) >> 2UL;
+ }
+ }
+ else if (hspi->Init.DataSize <= SPI_DATASIZE_16BIT)
+ {
+ if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
+ {
+ hspi->TxXferCount = (hspi->TxXferCount + (uint16_t) 1UL) >> 1UL;
+ }
+ if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_WORD)
+ {
+ hspi->RxXferCount = (hspi->RxXferCount + (uint16_t) 1UL) >> 1UL;
+ }
+ }
+ else
+ {
+ /* Adjustment done */
+ }
+
+ /* Check if we are in Rx only or in Rx/Tx Mode and configure the DMA transfer complete callback */
+ if (hspi->State == HAL_SPI_STATE_BUSY_RX)
+ {
+ /* Set the SPI Rx DMA Half transfer complete callback */
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
+ hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
+ }
+ else
+ {
+ /* Set the SPI Tx/Rx DMA Half transfer complete callback */
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt;
+ hspi->hdmarx->XferCpltCallback = SPI_DMATransmitReceiveCplt;
+ }
+
+ /* Set the DMA error callback */
+ hspi->hdmarx->XferErrorCallback = SPI_DMAError;
+
+ /* Set the DMA AbortCallback */
+ hspi->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the Rx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->RXDR, (uint32_t)hspi->pRxBuffPtr, hspi->RxXferCount))
+ {
+ /* Update SPI error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ hspi->State = HAL_SPI_STATE_READY;
+ return errorcode;
+ }
+
+ /* Enable Rx DMA Request */
+ SET_BIT(hspi->Instance->CFG1, SPI_CFG1_RXDMAEN);
+
+ /* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing
+ is performed in DMA reception complete callback */
+ hspi->hdmatx->XferHalfCpltCallback = NULL;
+ hspi->hdmatx->XferCpltCallback = NULL;
+ hspi->hdmatx->XferErrorCallback = NULL;
+ hspi->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the Tx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->TXDR, hspi->TxXferCount))
+ {
+ /* Update SPI error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ hspi->State = HAL_SPI_STATE_READY;
+ return errorcode;
+ }
+
+ if (hspi->hdmatx->Init.Mode == DMA_CIRCULAR)
+ {
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, 0UL);
+ }
+ else
+ {
+ MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
+ }
+
+ /* Enable Tx DMA Request */
+ SET_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN);
+
+ /* Enable the SPI Error Interrupt Bit */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_OVR | SPI_IT_UDR | SPI_IT_FRE | SPI_IT_MODF));
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ /* Master transfer start */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Abort ongoing transfer (blocking mode).
+ * @param hspi SPI handle.
+ * @note This procedure could be used for aborting any ongoing transfer (Tx and Rx),
+ * started in Interrupt or DMA mode.
+ * @note This procedure performs following operations :
+ * + Disable SPI Interrupts (depending of transfer direction)
+ * + Disable the DMA transfer in the peripheral register (if enabled)
+ * + Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * + Set handle State to READY.
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi)
+{
+ HAL_StatusTypeDef errorcode;
+
+ __IO uint32_t count;
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ /* Set hspi->state to aborting to avoid any interaction */
+ hspi->State = HAL_SPI_STATE_ABORT;
+
+ /* Initialized local variable */
+ errorcode = HAL_OK;
+ count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24UL / 1000UL);
+
+ /* If master communication on going, make sure current frame is done before closing the connection */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR1, SPI_CR1_CSTART))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSUSP);
+ do
+ {
+ count--;
+ if (count == 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ break;
+ }
+ }
+ while (HAL_IS_BIT_SET(hspi->Instance->CR1, SPI_CR1_CSTART));
+ }
+
+ /* Disable the SPI DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN))
+ {
+ if (hspi->hdmatx != NULL)
+ {
+ /* Abort the SPI DMA Tx Stream/Channel : use blocking DMA Abort API (no callback) */
+ hspi->hdmatx->XferAbortCallback = NULL;
+
+ /* Abort DMA Tx Handle linked to SPI Peripheral */
+ if (HAL_DMA_Abort(hspi->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hspi->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+ }
+ }
+ }
+
+ /* Disable the SPI DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hspi->Instance->CFG1, SPI_CFG1_RXDMAEN))
+ {
+ if (hspi->hdmarx != NULL)
+ {
+ /* Abort the SPI DMA Rx Stream/Channel : use blocking DMA Abort API (no callback) */
+ hspi->hdmarx->XferAbortCallback = NULL;
+
+ /* Abort DMA Rx Handle linked to SPI Peripheral */
+ if (HAL_DMA_Abort(hspi->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hspi->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+ }
+ }
+ }
+
+ /* Proceed with abort procedure */
+ SPI_AbortTransfer(hspi);
+
+ /* Check error during Abort procedure */
+ if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
+ {
+ /* return HAL_Error in case of error during Abort procedure */
+ errorcode = HAL_ERROR;
+ }
+ else
+ {
+ /* Reset errorCode */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ /* Restore hspi->state to ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+ return errorcode;
+}
+
+/**
+ * @brief Abort ongoing transfer (Interrupt mode).
+ * @param hspi SPI handle.
+ * @note This procedure could be used for aborting any ongoing transfer (Tx and Rx),
+ * started in Interrupt or DMA mode.
+ * @note This procedure performs following operations :
+ * + Disable SPI Interrupts (depending of transfer direction)
+ * + Disable the DMA transfer in the peripheral register (if enabled)
+ * + Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * + Set handle State to READY
+ * + At abort completion, call user abort complete callback.
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi)
+{
+ HAL_StatusTypeDef errorcode;
+ __IO uint32_t count;
+ uint32_t dma_tx_abort_done = 1UL, dma_rx_abort_done = 1UL;
+
+ /* Set hspi->state to aborting to avoid any interaction */
+ hspi->State = HAL_SPI_STATE_ABORT;
+
+ /* Initialized local variable */
+ errorcode = HAL_OK;
+ count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24UL / 1000UL);
+
+ /* If master communication on going, make sure current frame is done before closing the connection */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR1, SPI_CR1_CSTART))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CSUSP);
+ do
+ {
+ count--;
+ if (count == 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ break;
+ }
+ }
+ while (HAL_IS_BIT_SET(hspi->Instance->CR1, SPI_CR1_CSTART));
+ }
+
+ /* If DMA Tx and/or DMA Rx Handles are associated to SPI Handle, DMA Abort complete callbacks should be initialized
+ before any call to DMA Abort functions */
+
+ if(hspi->hdmatx != NULL)
+ {
+ if (HAL_IS_BIT_SET(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN))
+ {
+ /* Set DMA Abort Complete callback if SPI DMA Tx request if enabled */
+ hspi->hdmatx->XferAbortCallback = SPI_DMATxAbortCallback;
+
+ dma_tx_abort_done = 0UL;
+
+ /* Abort DMA Tx Handle linked to SPI Peripheral */
+ if (HAL_DMA_Abort_IT(hspi->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hspi->hdmatx) == HAL_DMA_ERROR_NO_XFER)
+ {
+ dma_tx_abort_done = 1UL;
+ hspi->hdmatx->XferAbortCallback = NULL;
+ }
+ }
+ }
+ else
+ {
+ hspi->hdmatx->XferAbortCallback = NULL;
+ }
+ }
+
+ if(hspi->hdmarx != NULL)
+ {
+ if (HAL_IS_BIT_SET(hspi->Instance->CFG1, SPI_CFG1_RXDMAEN))
+ {
+ /* Set DMA Abort Complete callback if SPI DMA Rx request if enabled */
+ hspi->hdmarx->XferAbortCallback = SPI_DMARxAbortCallback;
+
+ dma_rx_abort_done = 0UL;
+
+ /* Abort DMA Rx Handle linked to SPI Peripheral */
+ if (HAL_DMA_Abort_IT(hspi->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(hspi->hdmarx) == HAL_DMA_ERROR_NO_XFER)
+ {
+ dma_rx_abort_done = 1UL;
+ hspi->hdmarx->XferAbortCallback = NULL;
+ }
+ }
+ }
+ else
+ {
+ hspi->hdmarx->XferAbortCallback = NULL;
+ }
+ }
+
+ /* If no running DMA transfer, finish cleanup and call callbacks */
+ if ((dma_tx_abort_done == 1UL) && (dma_rx_abort_done == 1UL))
+ {
+ /* Proceed with abort procedure */
+ SPI_AbortTransfer(hspi);
+
+ /* Check error during Abort procedure */
+ if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
+ {
+ /* return HAL_Error in case of error during Abort procedure */
+ errorcode = HAL_ERROR;
+ }
+ else
+ {
+ /* Reset errorCode */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ }
+
+ /* Restore hspi->state to ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->AbortCpltCallback(hspi);
+#else
+ HAL_SPI_AbortCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+
+ return errorcode;
+}
+
+/**
+ * @brief Pause the DMA Transfer.
+ * This API is not supported, it is maintained for backward compatibility.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL_ERROR
+ */
+HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi)
+{
+ /* Set error code to not supported */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_NOT_SUPPORTED);
+
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Resume the DMA Transfer.
+ * This API is not supported, it is maintained for backward compatibility.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL_ERROR
+ */
+HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi)
+{
+ /* Set error code to not supported */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_NOT_SUPPORTED);
+
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Stop the DMA Transfer.
+ * This API is not supported, it is maintained for backward compatibility.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL_ERROR
+ */
+HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi)
+{
+ /* Set error code to not supported */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_NOT_SUPPORTED);
+
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Handle SPI interrupt request.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval None
+ */
+void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi)
+{
+ uint32_t itsource = hspi->Instance->IER;
+ uint32_t itflag = hspi->Instance->SR;
+ uint32_t trigger = itsource & itflag;
+ uint32_t cfg1 = hspi->Instance->CFG1;
+ uint32_t handled = 0UL;
+
+ HAL_SPI_StateTypeDef State = hspi->State;
+#if defined (__GNUC__)
+ __IO uint16_t *prxdr_16bits = (__IO uint16_t *)(&(hspi->Instance->RXDR));
+#endif /* __GNUC__ */
+
+
+ /* SPI in mode Transmitter and Receiver ------------------------------------*/
+ if (HAL_IS_BIT_CLR(trigger, SPI_FLAG_OVR) && HAL_IS_BIT_CLR(trigger, SPI_FLAG_UDR) && HAL_IS_BIT_SET(trigger, SPI_FLAG_DXP))
+ {
+ hspi->TxISR(hspi);
+ hspi->RxISR(hspi);
+ handled = 1UL;
+ }
+
+ /* SPI in mode Receiver ----------------------------------------------------*/
+ if (HAL_IS_BIT_CLR(trigger, SPI_FLAG_OVR) && HAL_IS_BIT_SET(trigger, SPI_FLAG_RXP) && HAL_IS_BIT_CLR(trigger, SPI_FLAG_DXP))
+ {
+ hspi->RxISR(hspi);
+ handled = 1UL;
+ }
+
+ /* SPI in mode Transmitter -------------------------------------------------*/
+ if (HAL_IS_BIT_CLR(trigger, SPI_FLAG_UDR) && HAL_IS_BIT_SET(trigger, SPI_FLAG_TXP) && HAL_IS_BIT_CLR(trigger, SPI_FLAG_DXP))
+ {
+ hspi->TxISR(hspi);
+ handled = 1UL;
+ }
+
+#if defined(USE_SPI_RELOAD_TRANSFER)
+ /* SPI Reload -------------------------------------------------*/
+ if (HAL_IS_BIT_SET(trigger, SPI_FLAG_TSERF))
+ {
+ hspi->Reload.Requested = 0UL;
+ __HAL_SPI_CLEAR_TSERFFLAG(hspi);
+ }
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+
+ if (handled != 0UL)
+ {
+ return;
+ }
+
+ /* SPI End Of Transfer: DMA or IT based transfer */
+ if (HAL_IS_BIT_SET(trigger, SPI_FLAG_EOT))
+ {
+ /* Clear EOT/TXTF/SUSP flag */
+ __HAL_SPI_CLEAR_EOTFLAG(hspi);
+ __HAL_SPI_CLEAR_TXTFFLAG(hspi);
+ __HAL_SPI_CLEAR_SUSPFLAG(hspi);
+
+ /* Disable EOT interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_EOT);
+
+ /* DMA Normal Mode */
+ if (HAL_IS_BIT_CLR(cfg1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN) || // IT based transfer is done
+ ((State != HAL_SPI_STATE_BUSY_RX) && (hspi->hdmatx->Init.Mode == DMA_NORMAL)) || // DMA is used in normal mode
+ ((State != HAL_SPI_STATE_BUSY_TX) && (hspi->hdmarx->Init.Mode == DMA_NORMAL))) // DMA is used in normal mode
+ {
+ /* For the IT based receive extra polling maybe required for last packet */
+ if (HAL_IS_BIT_CLR(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN))
+ {
+ /* Pooling remaining data */
+ while (hspi->RxXferCount != 0UL)
+ {
+ /* Receive data in 32 Bit mode */
+ if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
+ {
+ *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint32_t);
+ }
+ /* Receive data in 16 Bit mode */
+ else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+#if defined (__GNUC__)
+ *((uint16_t *)hspi->pRxBuffPtr) = *prxdr_16bits;
+#else
+ *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
+#endif /* __GNUC__ */
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ }
+ /* Receive data in 8 Bit mode */
+ else
+ {
+ *((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint8_t);
+ }
+
+ hspi->RxXferCount--;
+ }
+ }
+
+ /* Call SPI Standard close procedure */
+ SPI_CloseTransfer(hspi);
+
+ hspi->State = HAL_SPI_STATE_READY;
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ return;
+ }
+ }
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ /* Call appropriate user callback */
+ if (State == HAL_SPI_STATE_BUSY_TX_RX)
+ {
+ hspi->TxRxCpltCallback(hspi);
+ }
+ else if (State == HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->RxCpltCallback(hspi);
+ }
+ else if (State == HAL_SPI_STATE_BUSY_TX)
+ {
+ hspi->TxCpltCallback(hspi);
+ }
+#else
+ /* Call appropriate user callback */
+ if (State == HAL_SPI_STATE_BUSY_TX_RX)
+ {
+ HAL_SPI_TxRxCpltCallback(hspi);
+ }
+ else if (State == HAL_SPI_STATE_BUSY_RX)
+ {
+ HAL_SPI_RxCpltCallback(hspi);
+ }
+ else if (State == HAL_SPI_STATE_BUSY_TX)
+ {
+ HAL_SPI_TxCpltCallback(hspi);
+ }
+ else
+ {
+ /* end of the appropriate call */
+ }
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+
+ return;
+ }
+
+ if (HAL_IS_BIT_SET(itflag, SPI_FLAG_SUSP) && HAL_IS_BIT_SET(itsource, SPI_FLAG_EOT))
+ {
+ /* Abort on going, clear SUSP flag to avoid infinite looping */
+ __HAL_SPI_CLEAR_SUSPFLAG(hspi);
+
+ return;
+ }
+
+ /* SPI in Error Treatment --------------------------------------------------*/
+ if ((trigger & (SPI_FLAG_MODF | SPI_FLAG_OVR | SPI_FLAG_FRE | SPI_FLAG_UDR)) != 0UL)
+ {
+ /* SPI Overrun error interrupt occurred ----------------------------------*/
+ if ((trigger & SPI_FLAG_OVR) != 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR);
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+
+ /* SPI Mode Fault error interrupt occurred -------------------------------*/
+ if ((trigger & SPI_FLAG_MODF) != 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_MODF);
+ __HAL_SPI_CLEAR_MODFFLAG(hspi);
+ }
+
+ /* SPI Frame error interrupt occurred ------------------------------------*/
+ if ((trigger & SPI_FLAG_FRE) != 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FRE);
+ __HAL_SPI_CLEAR_FREFLAG(hspi);
+ }
+
+ /* SPI Underrun error interrupt occurred ------------------------------------*/
+ if ((trigger & SPI_FLAG_UDR) != 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_UDR);
+ __HAL_SPI_CLEAR_UDRFLAG(hspi);
+ }
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Disable all interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_EOT | SPI_IT_RXP | SPI_IT_TXP | SPI_IT_MODF | SPI_IT_OVR | SPI_IT_FRE | SPI_IT_UDR);
+
+ /* Disable the SPI DMA requests if enabled */
+ if (HAL_IS_BIT_SET(cfg1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN))
+ {
+ /* Disable the SPI DMA requests */
+ CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);
+
+ /* Abort the SPI DMA Rx channel */
+ if (hspi->hdmarx != NULL)
+ {
+ /* Set the SPI DMA Abort callback :
+ will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
+ hspi->hdmarx->XferAbortCallback = SPI_DMAAbortOnError;
+ if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmarx))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ }
+ }
+ /* Abort the SPI DMA Tx channel */
+ if (hspi->hdmatx != NULL)
+ {
+ /* Set the SPI DMA Abort callback :
+ will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
+ hspi->hdmatx->XferAbortCallback = SPI_DMAAbortOnError;
+ if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmatx))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ }
+ }
+ }
+ else
+ {
+ /* Restore hspi->State to Ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ }
+ return;
+ }
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_RxCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx and Rx Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxRxCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxHalfCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Half Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_RxHalfCpltCallback() should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx and Rx Half Transfer callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxRxHalfCpltCallback() should be implemented in the user file
+ */
+}
+
+/**
+ * @brief SPI error callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_ErrorCallback should be implemented in the user file
+ */
+ /* NOTE : The ErrorCode parameter in the hspi handle is updated by the SPI processes
+ and user can use HAL_SPI_GetError() API to check the latest error occurred
+ */
+}
+
+/**
+ * @brief SPI Abort Complete callback.
+ * @param hspi SPI handle.
+ * @retval None
+ */
+__weak void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_AbortCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief SPI control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the SPI.
+ (+) HAL_SPI_GetState() API can be helpful to check in run-time the state of the SPI peripheral
+ (+) HAL_SPI_GetError() check in run-time Errors occurring during communication
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the SPI handle state.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval SPI state
+ */
+HAL_SPI_StateTypeDef HAL_SPI_GetState(SPI_HandleTypeDef *hspi)
+{
+ /* Return SPI handle state */
+ return hspi->State;
+}
+
+/**
+ * @brief Return the SPI error code.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval SPI error code in bitmap format
+ */
+uint32_t HAL_SPI_GetError(SPI_HandleTypeDef *hspi)
+{
+ /* Return SPI ErrorCode */
+ return hspi->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup SPI_Private_Functions
+ * @brief Private functions
+ * @{
+ */
+
+/**
+ * @brief DMA SPI transmit process complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hspi->State != HAL_SPI_STATE_ABORT)
+ {
+ if (hspi->hdmatx->Init.Mode == DMA_CIRCULAR)
+ {
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->TxCpltCallback(hspi);
+#else
+ HAL_SPI_TxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Enable EOT interrupt */
+ __HAL_SPI_ENABLE_IT(hspi, SPI_IT_EOT);
+ }
+ }
+}
+
+/**
+ * @brief DMA SPI receive process complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hspi->State != HAL_SPI_STATE_ABORT)
+ {
+ if (hspi->hdmarx->Init.Mode == DMA_CIRCULAR)
+ {
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->RxCpltCallback(hspi);
+#else
+ HAL_SPI_RxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Enable EOT interrupt */
+ __HAL_SPI_ENABLE_IT(hspi, SPI_IT_EOT);
+ }
+ }
+}
+
+/**
+ * @brief DMA SPI transmit receive process complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hspi->State != HAL_SPI_STATE_ABORT)
+ {
+ if (hspi->hdmatx->Init.Mode == DMA_CIRCULAR)
+ {
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->TxRxCpltCallback(hspi);
+#else
+ HAL_SPI_TxRxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Enable EOT interrupt */
+ __HAL_SPI_ENABLE_IT(hspi, SPI_IT_EOT);
+ }
+ }
+}
+
+/**
+ * @brief DMA SPI half transmit process complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->TxHalfCpltCallback(hspi);
+#else
+ HAL_SPI_TxHalfCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI half receive process complete callback
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->RxHalfCpltCallback(hspi);
+#else
+ HAL_SPI_RxHalfCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI half transmit receive process complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->TxRxHalfCpltCallback(hspi);
+#else
+ HAL_SPI_TxRxHalfCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI communication error callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAError(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* if DMA error is FIFO error ignore it */
+ if (HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE)
+ {
+ /* Call SPI standard close procedure */
+ SPI_CloseTransfer(hspi);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ hspi->State = HAL_SPI_STATE_READY;
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief DMA SPI communication abort callback, when initiated by HAL services on Error
+ * (To be called at end of DMA Abort procedure following error occurrence).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+ hspi->RxXferCount = (uint16_t) 0UL;
+ hspi->TxXferCount = (uint16_t) 0UL;
+
+ /* Restore hspi->State to Ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI Tx communication abort callback, when initiated by user
+ * (To be called at end of DMA Tx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Rx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ hspi->hdmatx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (hspi->hdmarx != NULL)
+ {
+ if (hspi->hdmarx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* Call the Abort procedure */
+ SPI_AbortTransfer(hspi);
+
+ /* Restore hspi->State to Ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->AbortCpltCallback(hspi);
+#else
+ HAL_SPI_AbortCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI Rx communication abort callback, when initiated by user
+ * (To be called at end of DMA Rx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Tx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ hspi->hdmarx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (hspi->hdmatx != NULL)
+ {
+ if (hspi->hdmatx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* Call the Abort procedure */
+ SPI_AbortTransfer(hspi);
+
+ /* Restore hspi->State to Ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1UL)
+ hspi->AbortCpltCallback(hspi);
+#else
+ HAL_SPI_AbortCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief Manage the receive 8-bit in Interrupt context.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_8BIT(SPI_HandleTypeDef *hspi)
+{
+ /* Receive data in 8 Bit mode */
+ *((uint8_t *)hspi->pRxBuffPtr) = (*(__IO uint8_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint8_t);
+ hspi->RxXferCount--;
+
+ /* Disable IT if no more data excepted */
+ if (hspi->RxXferCount == 0UL)
+ {
+#if defined(USE_SPI_RELOAD_TRANSFER)
+ /* Check if there is any request to reload */
+ if (hspi->Reload.Requested == 1UL)
+ {
+ hspi->RxXferSize = hspi->Reload.RxXferSize;
+ hspi->RxXferCount = hspi->Reload.RxXferSize;
+ hspi->pRxBuffPtr = hspi->Reload.pRxBuffPtr;
+ }
+ else
+ {
+ /* Disable RXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXP);
+ }
+#else
+ /* Disable RXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXP);
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+ }
+}
+
+
+/**
+ * @brief Manage the 16-bit receive in Interrupt context.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_16BIT(SPI_HandleTypeDef *hspi)
+{
+ /* Receive data in 16 Bit mode */
+#if defined (__GNUC__)
+ __IO uint16_t *prxdr_16bits = (__IO uint16_t *)(&(hspi->Instance->RXDR));
+
+ *((uint16_t *)hspi->pRxBuffPtr) = *prxdr_16bits;
+#else
+ *((uint16_t *)hspi->pRxBuffPtr) = (*(__IO uint16_t *)&hspi->Instance->RXDR);
+#endif /* __GNUC__ */
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+
+ /* Disable IT if no more data excepted */
+ if (hspi->RxXferCount == 0UL)
+ {
+#if defined(USE_SPI_RELOAD_TRANSFER)
+ /* Check if there is any request to reload */
+ if (hspi->Reload.Requested == 1UL)
+ {
+ hspi->RxXferSize = hspi->Reload.RxXferSize;
+ hspi->RxXferCount = hspi->Reload.RxXferSize;
+ hspi->pRxBuffPtr = hspi->Reload.pRxBuffPtr;
+ }
+ else
+ {
+ /* Disable RXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXP);
+ }
+#else
+ /* Disable RXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXP);
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+ }
+}
+
+
+/**
+ * @brief Manage the 32-bit receive in Interrupt context.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_32BIT(SPI_HandleTypeDef *hspi)
+{
+ /* Receive data in 32 Bit mode */
+ *((uint32_t *)hspi->pRxBuffPtr) = (*(__IO uint32_t *)&hspi->Instance->RXDR);
+ hspi->pRxBuffPtr += sizeof(uint32_t);
+ hspi->RxXferCount--;
+
+ /* Disable IT if no more data excepted */
+ if (hspi->RxXferCount == 0UL)
+ {
+#if defined(USE_SPI_RELOAD_TRANSFER)
+ /* Check if there is any request to reload */
+ if (hspi->Reload.Requested == 1UL)
+ {
+ hspi->RxXferSize = hspi->Reload.RxXferSize;
+ hspi->RxXferCount = hspi->Reload.RxXferSize;
+ hspi->pRxBuffPtr = hspi->Reload.pRxBuffPtr;
+ }
+ else
+ {
+ /* Disable RXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXP);
+ }
+#else
+ /* Disable RXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXP);
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+ }
+}
+
+
+/**
+ * @brief Handle the data 8-bit transmit in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_TxISR_8BIT(SPI_HandleTypeDef *hspi)
+{
+ /* Transmit data in 8 Bit mode */
+ *(__IO uint8_t *)&hspi->Instance->TXDR = *((uint8_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint8_t);
+ hspi->TxXferCount--;
+
+ /* Disable IT if no more data excepted */
+ if (hspi->TxXferCount == 0UL)
+ {
+#if defined(USE_SPI_RELOAD_TRANSFER)
+ /* Check if there is any request to reload */
+ if (hspi->Reload.Requested == 1UL)
+ {
+ hspi->TxXferSize = hspi->Reload.TxXferSize;
+ hspi->TxXferCount = hspi->Reload.TxXferSize;
+ hspi->pTxBuffPtr = hspi->Reload.pTxBuffPtr;
+ }
+ else
+ {
+ /* Disable TXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXP);
+ }
+#else
+ /* Disable TXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXP);
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+ }
+}
+
+/**
+ * @brief Handle the data 16-bit transmit in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_TxISR_16BIT(SPI_HandleTypeDef *hspi)
+{
+ /* Transmit data in 16 Bit mode */
+#if defined (__GNUC__)
+ __IO uint16_t *ptxdr_16bits = (__IO uint16_t *)(&(hspi->Instance->TXDR));
+
+ *ptxdr_16bits = *((uint16_t *)hspi->pTxBuffPtr);
+#else
+ *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
+#endif /* __GNUC__ */
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+
+ /* Disable IT if no more data excepted */
+ if (hspi->TxXferCount == 0UL)
+ {
+#if defined(USE_SPI_RELOAD_TRANSFER)
+ /* Check if there is any request to reload */
+ if (hspi->Reload.Requested == 1UL)
+ {
+ hspi->TxXferSize = hspi->Reload.TxXferSize;
+ hspi->TxXferCount = hspi->Reload.TxXferSize;
+ hspi->pTxBuffPtr = hspi->Reload.pTxBuffPtr;
+ }
+ else
+ {
+ /* Disable TXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXP);
+ }
+#else
+ /* Disable TXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXP);
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+ }
+}
+
+/**
+ * @brief Handle the data 32-bit transmit in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_TxISR_32BIT(SPI_HandleTypeDef *hspi)
+{
+ /* Transmit data in 32 Bit mode */
+ *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint32_t);
+ hspi->TxXferCount--;
+
+ /* Disable IT if no more data excepted */
+ if (hspi->TxXferCount == 0UL)
+ {
+#if defined(USE_SPI_RELOAD_TRANSFER)
+ /* Check if there is any request to reload */
+ if (hspi->Reload.Requested == 1UL)
+ {
+ hspi->TxXferSize = hspi->Reload.TxXferSize;
+ hspi->TxXferCount = hspi->Reload.TxXferSize;
+ hspi->pTxBuffPtr = hspi->Reload.pTxBuffPtr;
+ }
+ else
+ {
+ /* Disable TXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXP);
+ }
+#else
+ /* Disable TXP interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXP);
+#endif /* USE_HSPI_RELOAD_TRANSFER */
+ }
+}
+
+/**
+ * @brief Abort Transfer and clear flags.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_AbortTransfer(SPI_HandleTypeDef *hspi)
+{
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Disable ITs */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_EOT | SPI_IT_TXP | SPI_IT_RXP | SPI_IT_DXP | SPI_IT_UDR | SPI_IT_OVR | SPI_IT_FRE | SPI_IT_MODF));
+
+ /* Clear the Status flags in the SR register */
+ __HAL_SPI_CLEAR_EOTFLAG(hspi);
+ __HAL_SPI_CLEAR_TXTFFLAG(hspi);
+
+ /* Disable Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);
+
+ /* Clear the Error flags in the SR register */
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ __HAL_SPI_CLEAR_UDRFLAG(hspi);
+ __HAL_SPI_CLEAR_FREFLAG(hspi);
+ __HAL_SPI_CLEAR_MODFFLAG(hspi);
+ __HAL_SPI_CLEAR_SUSPFLAG(hspi);
+
+#if (USE_SPI_CRC != 0U)
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+#endif /* USE_SPI_CRC */
+
+ hspi->TxXferCount = (uint16_t)0UL;
+ hspi->RxXferCount = (uint16_t)0UL;
+}
+
+
+/**
+ * @brief Close Transfer and clear flags.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval HAL_ERROR: if any error detected
+* HAL_OK: if nothing detected
+ */
+static void SPI_CloseTransfer(SPI_HandleTypeDef *hspi)
+{
+ uint32_t itflag = hspi->Instance->SR;
+
+ __HAL_SPI_CLEAR_EOTFLAG(hspi);
+ __HAL_SPI_CLEAR_TXTFFLAG(hspi);
+
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Disable ITs */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_EOT | SPI_IT_TXP | SPI_IT_RXP | SPI_IT_DXP | SPI_IT_UDR | SPI_IT_OVR | SPI_IT_FRE | SPI_IT_MODF));
+
+ /* Disable Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);
+
+ /* Report UnderRun error for non RX Only communication */
+ if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+ {
+ if ((itflag & SPI_FLAG_UDR) != 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_UDR);
+ __HAL_SPI_CLEAR_UDRFLAG(hspi);
+ }
+ }
+
+ /* Report OverRun error for non TX Only communication */
+ if (hspi->State != HAL_SPI_STATE_BUSY_TX)
+ {
+ if ((itflag & SPI_FLAG_OVR) != 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR);
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+
+#if (USE_SPI_CRC != 0UL)
+ /* Check if CRC error occurred */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ if ((itflag & SPI_FLAG_CRCERR) != 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ }
+ }
+#endif /* USE_SPI_CRC */
+ }
+
+ /* SPI Mode Fault error interrupt occurred -------------------------------*/
+ if ((itflag & SPI_FLAG_MODF) != 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_MODF);
+ __HAL_SPI_CLEAR_MODFFLAG(hspi);
+ }
+
+ /* SPI Frame error interrupt occurred ------------------------------------*/
+ if ((itflag & SPI_FLAG_FRE) != 0UL)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FRE);
+ __HAL_SPI_CLEAR_FREFLAG(hspi);
+ }
+
+ hspi->TxXferCount = (uint16_t)0UL;
+ hspi->RxXferCount = (uint16_t)0UL;
+}
+
+/**
+ * @brief Handle SPI Communication Timeout.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param Flag: SPI flag to check
+ * @param Status: flag state to check
+ * @param Timeout: Timeout duration
+ * @param Tickstart: Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPI_WaitOnFlagUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus Status,
+ uint32_t Tickstart, uint32_t Timeout)
+{
+ /* Wait until flag is set */
+ while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) == Status)
+ {
+ /* Check for the Timeout */
+ if ((((HAL_GetTick() - Tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Compute configured packet size from fifo perspective.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval Packet size occupied in the fifo
+ */
+static uint32_t SPI_GetPacketSize(SPI_HandleTypeDef *hspi)
+{
+ uint32_t fifo_threashold = (hspi->Init.FifoThreshold >> SPI_CFG1_FTHLV_Pos) + 1UL;
+ uint32_t data_size = (hspi->Init.DataSize >> SPI_CFG1_DSIZE_Pos) + 1UL;
+
+ /* Convert data size to Byte */
+ data_size = (data_size + 7UL) / 8UL;
+
+ return data_size * fifo_threashold;
+}
+
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_spi_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_spi_ex.c
new file mode 100644
index 0000000000..5549d0b590
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_spi_ex.c
@@ -0,0 +1,229 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_spi_ex.c
+ * @author MCD Application Team
+ * @brief Extended SPI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * SPI peripheral extended functionalities :
+ * + IO operation functions
+ * + Peripheral Control functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SPIEx SPIEx
+ * @brief SPI Extended HAL module driver
+ * @{
+ */
+#ifdef HAL_SPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup SPIEx_Exported_Functions SPIEx Exported Functions
+ * @{
+ */
+
+/** @defgroup SPIEx_Exported_Functions_Group1 IO operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of extended functions to manage the SPI
+ data transfers.
+
+ (#) SPIEx function:
+ (++) HAL_SPIEx_FlushRxFifo()
+ (++) HAL_SPIEx_FlushRxFifo()
+ (++) HAL_SPIEx_EnableLockConfiguration()
+ (++) HAL_SPIEx_ConfigureUnderrun()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Flush the RX fifo.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(SPI_HandleTypeDef *hspi)
+{
+ uint8_t count = 0;
+ uint32_t itflag = hspi->Instance->SR;
+ __IO uint32_t tmpreg;
+
+ while (((hspi->Instance->SR & SPI_FLAG_FRLVL) != SPI_RX_FIFO_0PACKET) || ((itflag & SPI_FLAG_RXWNE) != 0UL))
+ {
+ count += (uint8_t)4UL;
+ tmpreg = hspi->Instance->RXDR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+
+ if (IS_SPI_HIGHEND_INSTANCE(hspi->Instance))
+ {
+ if (count > SPI_HIGHEND_FIFO_SIZE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ else
+ {
+ if (count > SPI_LOWEND_FIFO_SIZE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Enable the Lock for the AF configuration of associated IOs
+ * and write protect the Content of Configuration register 2
+ * when SPI is enabled
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_SPIEx_EnableLockConfiguration(SPI_HandleTypeDef *hspi)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Check if the SPI is disabled to edit IOLOCK bit */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_IOLOCK);
+ }
+ else
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_IOLOCK);
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Configure the UNDERRUN condition and behavior of slave transmitter.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param UnderrunDetection : Detection of underrun condition at slave transmitter
+ * This parameter can be a value of @ref SPI_Underrun_Detection.
+ * @param UnderrunBehaviour : Behavior of slave transmitter at underrun condition
+ * This parameter can be a value of @ref SPI_Underrun_Behaviour.
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_SPIEx_ConfigureUnderrun(SPI_HandleTypeDef *hspi, uint32_t UnderrunDetection, uint32_t UnderrunBehaviour)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Check State and Insure that Underrun configuration is managed only by Salve */
+ if ((hspi->State != HAL_SPI_STATE_READY) || (hspi->Init.Mode != SPI_MODE_SLAVE))
+ {
+ errorcode = HAL_BUSY;
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SPI_UNDERRUN_DETECTION(UnderrunDetection));
+ assert_param(IS_SPI_UNDERRUN_BEHAVIOUR(UnderrunBehaviour));
+
+ /* Check if the SPI is disabled to edit CFG1 register */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Configure Underrun fields */
+ MODIFY_REG(hspi->Instance->CFG1, SPI_CFG1_UDRDET, UnderrunDetection);
+ MODIFY_REG(hspi->Instance->CFG1, SPI_CFG1_UDRCFG, UnderrunBehaviour);
+ }
+ else
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Configure Underrun fields */
+ MODIFY_REG(hspi->Instance->CFG1, SPI_CFG1_UDRDET, UnderrunDetection);
+ MODIFY_REG(hspi->Instance->CFG1, SPI_CFG1_UDRCFG, UnderrunBehaviour);
+
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_sram.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sram.c
new file mode 100644
index 0000000000..258e0838e7
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_sram.c
@@ -0,0 +1,1113 @@
+/**
+ ******************************************************************************
+ * @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.
+ *
+ @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 @ref 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 @ref HAL_SRAM_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) 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 @ref HAL_SRAM_Init and if the state is HAL_SRAM_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_SRAM_Init
+ and @ref HAL_SRAM_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_SRAM_Init and @ref 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 @ref HAL_SRAM_RegisterCallback before calling @ref HAL_SRAM_DeInit
+ or @ref 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 (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_SRAM_MODULE_ENABLED
+
+/** @defgroup SRAM SRAM
+ * @brief SRAM driver modules
+ * @{
+ */
+
+/**
+ @cond 0
+ */
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void SRAM_DMACplt (MDMA_HandleTypeDef *hmdma);
+static void SRAM_DMACpltProt(MDMA_HandleTypeDef *hmdma);
+static void SRAM_DMAError (MDMA_HandleTypeDef *hmdma);
+/**
+ @endcond
+ */
+
+/* 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
+ }
+
+ /* 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
+
+ /* 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 mulitple */
+ 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 mulitple */
+ 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
+ {
+ return 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
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+}
+
+#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User SRAM Callback
+ * To be used instead of the weak (surcharged) 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;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hsram);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsram);
+ return status;
+}
+
+/**
+ * @brief Unregister a User SRAM Callback
+ * SRAM Callback is redirected to the weak (surcharged) 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;
+
+ /* Process locked */
+ __HAL_LOCK(hsram);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsram);
+ return status;
+}
+
+/**
+ * @brief Register a User SRAM Callback for DMA transfers
+ * To be used instead of the weak (surcharged) 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
+
+/**
+ * @}
+ */
+
+/** @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(SRAM_HandleTypeDef *hsram)
+{
+ return hsram->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ @cond 0
+ */
+/**
+ * @brief MDMA SRAM process complete callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SRAM_DMACplt(MDMA_HandleTypeDef *hmdma)
+{
+ 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
+}
+
+/**
+ * @brief MDMA SRAM process complete callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SRAM_DMACpltProt(MDMA_HandleTypeDef *hmdma)
+{
+ 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
+}
+
+/**
+ * @brief MDMA SRAM error callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SRAM_DMAError(MDMA_HandleTypeDef *hmdma)
+{
+ 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
+}
+/**
+ @endcond
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SRAM_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_swpmi.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_swpmi.c
new file mode 100644
index 0000000000..18dace284e
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_swpmi.c
@@ -0,0 +1,1949 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_swpmi.c
+ * @author MCD Application Team
+ * @brief SWPMI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Single Wire Protocol Master Interface (SWPMI).
+ * + Initialization and Configuration
+ * + Data transfers functions
+ * + DMA transfers management
+ * + Interrupts and flags management
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The SWPMI HAL driver can be used as follows:
+
+ (#) Declare a SWPMI_HandleTypeDef handle structure (eg. SWPMI_HandleTypeDef hswpmi).
+
+ (#) Initialize the SWPMI low level resources by implementing the HAL_SWPMI_MspInit() API:
+ (##) Enable the SWPMIx interface clock with __HAL_RCC_SWPMIx_CLK_ENABLE().
+ (##) SWPMI IO configuration:
+ (+++) Enable the clock for the SWPMI GPIO.
+ (+++) Configure these SWPMI pins as alternate function pull-up.
+ (##) NVIC configuration if you need to use interrupt process (HAL_SWPMI_Transmit_IT()
+ and HAL_SWPMI_Receive_IT() APIs):
+ (+++) Configure the SWPMIx interrupt priority with HAL_NVIC_SetPriority().
+ (+++) Enable the NVIC SWPMI IRQ handle with HAL_NVIC_EnableIRQ().
+
+ (##) DMA Configuration if you need to use DMA process (HAL_SWPMI_Transmit_DMA()
+ and HAL_SWPMI_Receive_DMA() APIs):
+ (+++) Declare a DMA handle structure for the Tx/Rx streams.
+ (+++) Enable the DMAx interface clock.
+ (+++) Configure the declared DMA handle structure with the required
+ Tx/Rx parameters.
+ (+++) Configure the DMA Tx/Rx streams and requests.
+ (+++) Associate the initialized DMA handle to the SWPMI DMA Tx/Rx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete
+ interrupt on the DMA Tx/Rx streams.
+
+ (#) Program the Bite Rate, Tx Buffering mode, Rx Buffering mode in the Init structure.
+
+ (#) Enable the SWPMI peripheral by calling the HAL_SWPMI_Init() function.
+
+ [..]
+ Three operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Send an amount of data in blocking mode using HAL_SWPMI_Transmit()
+ (+) Receive an amount of data in blocking mode using HAL_SWPMI_Receive()
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Send an amount of data in non-blocking mode using HAL_SWPMI_Transmit_IT()
+ (+) At transmission end of transfer HAL_SWPMI_TxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SWPMI_TxCpltCallback()
+ (+) Receive an amount of data in non-blocking mode using HAL_SWPMI_Receive_IT()
+ (+) At reception end of transfer HAL_SWPMI_RxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SWPMI_RxCpltCallback()
+ (+) In case of flag error, HAL_SWPMI_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_SWPMI_ErrorCallback()
+
+ *** DMA mode IO operation ***
+ =============================
+ [..]
+ (+) Send an amount of data in non-blocking mode (DMA) using HAL_SWPMI_Transmit_DMA()
+ (+) At transmission end of transfer HAL_SWPMI_TxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SWPMI_TxCpltCallback()
+ (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SWPMI_Receive_DMA()
+ (+) At reception end of transfer HAL_SWPMI_RxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SWPMI_RxCpltCallback()
+ (+) In case of flag error, HAL_SWPMI_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_SWPMI_ErrorCallback()
+ (+) Stop the DMA Transfer using HAL_SWPMI_DMAStop()
+
+ *** SWPMI HAL driver additional function list ***
+ ===============================================
+ [..]
+ Below the list the others API available SWPMI HAL driver :
+
+ (+) HAL_SWPMI_EnableLoopback(): Enable the loopback mode for test purpose only
+ (+) HAL_SWPMI_DisableLoopback(): Disable the loopback mode
+
+ *** SWPMI HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in SWPMI HAL driver :
+
+ (+) __HAL_SWPMI_ENABLE(): Enable the SWPMI peripheral
+ (+) __HAL_SWPMI_DISABLE(): Disable the SWPMI peripheral
+ (+) __HAL_SWPMI_TRANSCEIVER_ENABLE(): Enable the SWPMI peripheral transceiver
+ (+) __HAL_SWPMI_TRANSCEIVER_DISABLE(): Disable the SWPMI peripheral transceiver
+ (+) __HAL_SWPMI_ENABLE_IT(): Enable the specified SWPMI interrupts
+ (+) __HAL_SWPMI_DISABLE_IT(): Disable the specified SWPMI interrupts
+ (+) __HAL_SWPMI_GET_IT_SOURCE(): Check if the specified SWPMI interrupt source is
+ enabled or disabled
+ (+) __HAL_SWPMI_GET_FLAG(): Check whether the specified SWPMI flag is set or not
+
+ *** Callback registration ***
+ =============================
+ [..]
+ The compilation define USE_HAL_SWPMI_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ [..]
+ Use function HAL_SWPMI_RegisterCallback() to register a user callback. It allows
+ to register the following callbacks:
+ (+) RxCpltCallback : SWPMI receive complete.
+ (+) RxHalfCpltCallback : SWPMI receive half complete.
+ (+) TxCpltCallback : SWPMI transmit complete.
+ (+) TxHalfCpltCallback : SWPMI transmit half complete.
+ (+) ErrorCallback : SWPMI error.
+ (+) MspInitCallback : SWPMI MspInit.
+ (+) MspDeInitCallback : SWPMI MspDeInit.
+ [..]
+ This function takes as parameters the HAL peripheral handle, the callback ID
+ and a pointer to the user callback function.
+ [..]
+ Use function HAL_SWPMI_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function.
+ HAL_SWPMI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the callback ID.
+ This function allows to reset following callbacks:
+ (+) RxCpltCallback : SWPMI receive complete.
+ (+) RxHalfCpltCallback : SWPMI receive half complete.
+ (+) TxCpltCallback : SWPMI transmit complete.
+ (+) TxHalfCpltCallback : SWPMI transmit half complete.
+ (+) ErrorCallback : SWPMI error.
+ (+) MspInitCallback : SWPMI MspInit.
+ (+) MspDeInitCallback : SWPMI MspDeInit.
+ [..]
+ By default, after the HAL_SWPMI_Init and if the state is HAL_SWPMI_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (surcharged) functions:
+ examples HAL_SWPMI_RxCpltCallback(), HAL_SWPMI_ErrorCallback().
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (surcharged) functions in the HAL_SWPMI_Init
+ and HAL_SWPMI_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_SWPMI_Init and HAL_SWPMI_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_SWPMI_RegisterCallback before calling @ref HAL_SWPMI_DeInit
+ or HAL_SWPMI_Init function.
+ [..]
+ When the compilation define USE_HAL_SWPMI_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+
+/** @defgroup SWPMI SWPMI
+ * @brief HAL SWPMI module driver
+ * @{
+ */
+#ifdef HAL_SWPMI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup SWPMI_Private_Constants SWPMI Private Constants
+ * @{
+ */
+#define SWPMI_TIMEOUT_VALUE 22000U /* End of transmission timeout */
+#define SWPMI_TRANSCEIVER_RDY_TIMEOUT_VALUE 2000U /* Transceiver ready timeout */
+
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void SWPMI_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void SWPMI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
+static void SWPMI_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SWPMI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
+static void SWPMI_DMAError(DMA_HandleTypeDef *hdma);
+static void SWPMI_DMAAbortOnError(DMA_HandleTypeDef *hdma);
+static void SWPMI_Transmit_IT(SWPMI_HandleTypeDef *hswpmi);
+static void SWPMI_EndTransmit_IT(SWPMI_HandleTypeDef *hswpmi);
+static void SWPMI_Receive_IT(SWPMI_HandleTypeDef *hswpmi);
+static void SWPMI_EndReceive_IT(SWPMI_HandleTypeDef *hswpmi);
+static void SWPMI_EndTransmitReceive_IT(SWPMI_HandleTypeDef *hswpmi);
+static HAL_StatusTypeDef SWPMI_WaitOnFlagSetUntilTimeout(SWPMI_HandleTypeDef *hswpmi, uint32_t Flag, uint32_t Tickstart, uint32_t Timeout);
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup SWPMI_Exported_Functions SWPMI Exported Functions
+ * @{
+ */
+
+/** @defgroup SWPMI_Exported_Group1 Initialization/de-initialization methods
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the SWPMI peripheral.
+ (+) De-initialize the SWPMI peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the SWPMI peripheral according to the specified parameters in the SWPMI_InitTypeDef.
+ * @param hswpmi SWPMI handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SWPMI_Init(SWPMI_HandleTypeDef *hswpmi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the SWPMI handle allocation */
+ if(hswpmi == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameters */
+ assert_param(IS_SWPMI_VOLTAGE_CLASS(hswpmi->Init.VoltageClass));
+ assert_param(IS_SWPMI_BITRATE_VALUE(hswpmi->Init.BitRate));
+ assert_param(IS_SWPMI_TX_BUFFERING_MODE(hswpmi->Init.TxBufferingMode));
+ assert_param(IS_SWPMI_RX_BUFFERING_MODE(hswpmi->Init.RxBufferingMode));
+
+ if(hswpmi->State == HAL_SWPMI_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hswpmi->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ /* Reset callback pointers to the weak predefined callbacks */
+ hswpmi->RxCpltCallback = HAL_SWPMI_RxCpltCallback;
+ hswpmi->RxHalfCpltCallback = HAL_SWPMI_RxHalfCpltCallback;
+ hswpmi->TxCpltCallback = HAL_SWPMI_TxCpltCallback;
+ hswpmi->TxHalfCpltCallback = HAL_SWPMI_TxHalfCpltCallback;
+ hswpmi->ErrorCallback = HAL_SWPMI_ErrorCallback;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ if(hswpmi->MspInitCallback == NULL)
+ {
+ hswpmi->MspInitCallback = HAL_SWPMI_MspInit;
+ }
+ hswpmi->MspInitCallback(hswpmi);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_SWPMI_MspInit(hswpmi);
+#endif
+ }
+
+ hswpmi->State = HAL_SWPMI_STATE_BUSY;
+
+ /* Disable SWPMI interface */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+
+ /* Clear all SWPMI interface flags */
+ WRITE_REG(hswpmi->Instance->ICR, 0x099F);
+
+ /* Apply Voltage class selection */
+ MODIFY_REG(hswpmi->Instance->OR, SWPMI_OR_CLASS, hswpmi->Init.VoltageClass);
+
+
+ /* Configure the BRR register (Bitrate) */
+ WRITE_REG(hswpmi->Instance->BRR, hswpmi->Init.BitRate);
+
+ /* Apply SWPMI CR configuration */
+ MODIFY_REG(hswpmi->Instance->CR, \
+ SWPMI_CR_RXDMA | SWPMI_CR_TXDMA | SWPMI_CR_RXMODE | SWPMI_CR_TXMODE, \
+ hswpmi->Init.TxBufferingMode | hswpmi->Init.RxBufferingMode);
+
+ /* Enable the SWPMI transceiver */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPEN);
+ /* Wait on RDYF flag to activate SWPMI */
+ if(SWPMI_WaitOnFlagSetUntilTimeout(hswpmi, SWPMI_FLAG_RDYF, tickstart, SWPMI_TRANSCEIVER_RDY_TIMEOUT_VALUE) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ }
+
+ if(status == HAL_OK)
+ {
+ hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE;
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+
+ /* Enable SWPMI peripheral */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+ }
+ else
+ {
+ hswpmi->ErrorCode = HAL_SWPMI_ERROR_TRANSCEIVER_NOT_READY;
+ hswpmi->State = HAL_SWPMI_STATE_ERROR;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief De-initialize the SWPMI peripheral.
+ * @param hswpmi SWPMI handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SWPMI_DeInit(SWPMI_HandleTypeDef *hswpmi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the SWPMI handle allocation */
+ if(hswpmi == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameters */
+ assert_param(IS_SWPMI_INSTANCE(hswpmi->Instance));
+
+ hswpmi->State = HAL_SWPMI_STATE_BUSY;
+
+ /* Disable SWPMI interface */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+
+ /* Disable Loopback mode */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_LPBK);
+
+ /* Disable SWPMI transceiver */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPEN);
+
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ if(hswpmi->MspDeInitCallback == NULL)
+ {
+ hswpmi->MspDeInitCallback = HAL_SWPMI_MspDeInit;
+ }
+ hswpmi->MspDeInitCallback(hswpmi);
+#else
+ HAL_SWPMI_MspDeInit(hswpmi);
+#endif
+
+ hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE;
+ hswpmi->State = HAL_SWPMI_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hswpmi);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Initialize the SWPMI MSP.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+__weak void HAL_SWPMI_MspInit(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hswpmi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SWPMI_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the SWPMI MSP.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+__weak void HAL_SWPMI_MspDeInit(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hswpmi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SWPMI_MspDeInit can be implemented in the user file
+ */
+}
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a user SWPMI callback
+ * to be used instead of the weak predefined callback.
+ * @param hswpmi SWPMI handle.
+ * @param CallbackID ID of the callback to be registered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SWPMI_RX_COMPLETE_CB_ID receive complete callback ID.
+ * @arg @ref HAL_SWPMI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
+ * @arg @ref HAL_SWPMI_TX_COMPLETE_CB_ID transmit complete callback ID.
+ * @arg @ref HAL_SWPMI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
+ * @arg @ref HAL_SWPMI_ERROR_CB_ID error callback ID.
+ * @arg @ref HAL_SWPMI_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_SWPMI_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @param pCallback pointer to the callback function.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_SWPMI_RegisterCallback(SWPMI_HandleTypeDef *hswpmi,
+ HAL_SWPMI_CallbackIDTypeDef CallbackID,
+ pSWPMI_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* update the error code */
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ if(hswpmi->State == HAL_SWPMI_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SWPMI_RX_COMPLETE_CB_ID :
+ hswpmi->RxCpltCallback = pCallback;
+ break;
+ case HAL_SWPMI_RX_HALFCOMPLETE_CB_ID :
+ hswpmi->RxHalfCpltCallback = pCallback;
+ break;
+ case HAL_SWPMI_TX_COMPLETE_CB_ID :
+ hswpmi->TxCpltCallback = pCallback;
+ break;
+ case HAL_SWPMI_TX_HALFCOMPLETE_CB_ID :
+ hswpmi->TxHalfCpltCallback = pCallback;
+ break;
+ case HAL_SWPMI_ERROR_CB_ID :
+ hswpmi->ErrorCallback = pCallback;
+ break;
+ case HAL_SWPMI_MSPINIT_CB_ID :
+ hswpmi->MspInitCallback = pCallback;
+ break;
+ case HAL_SWPMI_MSPDEINIT_CB_ID :
+ hswpmi->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update the error code */
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(hswpmi->State == HAL_SWPMI_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SWPMI_MSPINIT_CB_ID :
+ hswpmi->MspInitCallback = pCallback;
+ break;
+ case HAL_SWPMI_MSPDEINIT_CB_ID :
+ hswpmi->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update the error code */
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Unregister a user SWPMI callback.
+ * SWPMI callback is redirected to the weak predefined callback.
+ * @param hswpmi SWPMI handle.
+ * @param CallbackID ID of the callback to be unregistered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SWPMI_RX_COMPLETE_CB_ID receive complete callback ID.
+ * @arg @ref HAL_SWPMI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
+ * @arg @ref HAL_SWPMI_TX_COMPLETE_CB_ID transmit complete callback ID.
+ * @arg @ref HAL_SWPMI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
+ * @arg @ref HAL_SWPMI_ERROR_CB_ID error callback ID.
+ * @arg @ref HAL_SWPMI_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_SWPMI_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_SWPMI_UnRegisterCallback(SWPMI_HandleTypeDef *hswpmi,
+ HAL_SWPMI_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(hswpmi->State == HAL_SWPMI_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SWPMI_RX_COMPLETE_CB_ID :
+ hswpmi->RxCpltCallback = HAL_SWPMI_RxCpltCallback;
+ break;
+ case HAL_SWPMI_RX_HALFCOMPLETE_CB_ID :
+ hswpmi->RxHalfCpltCallback = HAL_SWPMI_RxHalfCpltCallback;
+ break;
+ case HAL_SWPMI_TX_COMPLETE_CB_ID :
+ hswpmi->TxCpltCallback = HAL_SWPMI_TxCpltCallback;
+ break;
+ case HAL_SWPMI_TX_HALFCOMPLETE_CB_ID :
+ hswpmi->TxHalfCpltCallback = HAL_SWPMI_TxHalfCpltCallback;
+ break;
+ case HAL_SWPMI_ERROR_CB_ID :
+ hswpmi->ErrorCallback = HAL_SWPMI_ErrorCallback;
+ break;
+ case HAL_SWPMI_MSPINIT_CB_ID :
+ hswpmi->MspInitCallback = HAL_SWPMI_MspInit;
+ break;
+ case HAL_SWPMI_MSPDEINIT_CB_ID :
+ hswpmi->MspDeInitCallback = HAL_SWPMI_MspDeInit;
+ break;
+ default :
+ /* update the error code */
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if(hswpmi->State == HAL_SWPMI_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SWPMI_MSPINIT_CB_ID :
+ hswpmi->MspInitCallback = HAL_SWPMI_MspInit;
+ break;
+ case HAL_SWPMI_MSPDEINIT_CB_ID :
+ hswpmi->MspDeInitCallback = HAL_SWPMI_MspDeInit;
+ break;
+ default :
+ /* update the error code */
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ return status;
+}
+#endif /* USE_HAL_SWPMI_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup SWPMI_Exported_Group2 IO operation methods
+ * @brief SWPMI Transmit/Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation methods #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the SWPMI
+ data transfers.
+
+ (#) There are two modes of transfer:
+ (++) Blocking mode: The communication is performed in polling mode.
+ The HAL status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) Non-Blocking mode: The communication is performed using Interrupts
+ or DMA. The end of the data processing will be indicated through the
+ dedicated SWPMI Interrupt handler (HAL_SWPMI_IRQHandler()) when using Interrupt mode or
+ the selected DMA stream interrupt handler when using DMA mode.
+ The HAL_SWPMI_TxCpltCallback(), HAL_SWPMI_RxCpltCallback() user callbacks
+ will be executed respectively at the end of the transmit or receive process.
+ The HAL_SWPMI_ErrorCallback() user callback will be executed when a communication error is detected.
+
+ (#) Blocking mode API's are:
+ (++) HAL_SWPMI_Transmit()
+ (++) HAL_SWPMI_Receive()
+
+ (#) Non-Blocking mode API's with Interrupt are:
+ (++) HAL_SWPMI_Transmit_IT()
+ (++) HAL_SWPMI_Receive_IT()
+ (++) HAL_SWPMI_IRQHandler()
+
+ (#) Non-Blocking mode API's with DMA are:
+ (++) HAL_SWPMI_Transmit_DMA()
+ (++) HAL_SWPMI_Receive_DMA()
+ (++) HAL_SWPMI_DMAPause()
+ (++) HAL_SWPMI_DMAResume()
+ (++) HAL_SWPMI_DMAStop()
+
+ (#) A set of Transfer Complete Callbacks are provided in Non-Blocking mode:
+ (++) HAL_SWPMI_TxHalfCpltCallback()
+ (++) HAL_SWPMI_TxCpltCallback()
+ (++) HAL_SWPMI_RxHalfCpltCallback()
+ (++) HAL_SWPMI_RxCpltCallback()
+ (++) HAL_SWPMI_ErrorCallback()
+
+ (#) The capability to launch the above IO operations in loopback mode for
+ user application verification:
+ (++) HAL_SWPMI_EnableLoopback()
+ (++) HAL_SWPMI_DisableLoopback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmit an amount of data in blocking mode.
+ * @param hswpmi pointer to a SWPMI_HandleTypeDef structure that contains
+ * the configuration information for SWPMI 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_SWPMI_Transmit(SWPMI_HandleTypeDef *hswpmi, uint32_t* pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SWPMI_StateTypeDef tmp_state;
+ uint32_t *ptmp_data;
+ uint32_t tmp_size;
+
+ if((pData == NULL ) || (Size == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Process Locked */
+ __HAL_LOCK(hswpmi);
+
+ tmp_state = hswpmi->State;
+ if((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_RX))
+ {
+ /* Check if a non-blocking receive process is ongoing or not */
+ if(tmp_state == HAL_SWPMI_STATE_READY)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX;
+
+ /* Disable any transmitter interrupts */
+ __HAL_SWPMI_DISABLE_IT(hswpmi, SWPMI_IT_TCIE | SWPMI_IT_TIE | SWPMI_IT_TXUNRIE | SWPMI_IT_TXBEIE);
+
+ /* Disable any transmitter flags */
+ __HAL_SWPMI_CLEAR_FLAG(hswpmi, SWPMI_FLAG_TXBEF | SWPMI_FLAG_TXUNRF | SWPMI_FLAG_TCF);
+
+ /* Enable SWPMI peripheral if not */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX;
+ }
+
+ ptmp_data = pData;
+ tmp_size = Size;
+ do
+ {
+ /* Wait the TXE to write data */
+ if(HAL_IS_BIT_SET(hswpmi->Instance->ISR, SWPMI_FLAG_TXE))
+ {
+ hswpmi->Instance->TDR = *ptmp_data;
+ ptmp_data++;
+ tmp_size--;
+ }
+ else
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+ }
+ } while(tmp_size != 0U);
+
+ /* Wait on TXBEF flag to be able to start a second transfer */
+ if(SWPMI_WaitOnFlagSetUntilTimeout(hswpmi, SWPMI_FLAG_TXBEF, tickstart, Timeout) != HAL_OK)
+ {
+ /* Timeout occurred */
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_TXBEF_TIMEOUT;
+
+ status = HAL_TIMEOUT;
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Check if a non-blocking receive Process is ongoing or not */
+ if(hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_RX;
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+ }
+
+ if((status != HAL_OK) && (status != HAL_BUSY))
+ {
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+ }
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param hswpmi pointer to a SWPMI_HandleTypeDef structure that contains
+ * the configuration information for SWPMI 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_SWPMI_Receive(SWPMI_HandleTypeDef *hswpmi, uint32_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SWPMI_StateTypeDef tmp_state;
+ uint32_t *ptmp_data;
+ uint32_t tmp_size;
+
+ if((pData == NULL ) || (Size == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Process Locked */
+ __HAL_LOCK(hswpmi);
+
+ tmp_state = hswpmi->State;
+ if((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX))
+ {
+ /* Check if a non-blocking transmit process is ongoing or not */
+ if(tmp_state == HAL_SWPMI_STATE_READY)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_RX;
+
+ /* Disable any receiver interrupts */
+ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_SRIE | SWPMI_IT_RIE | SWPMI_IT_RXBERIE | SWPMI_IT_RXOVRIE | SWPMI_IT_RXBFIE);
+
+ /* Enable SWPMI peripheral if not */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX;
+ }
+
+ ptmp_data = pData;
+ tmp_size = Size;
+ do
+ {
+ /* Wait the RXNE to read data */
+ if(HAL_IS_BIT_SET(hswpmi->Instance->ISR, SWPMI_FLAG_RXNE))
+ {
+ *ptmp_data = hswpmi->Instance->RDR;
+ ptmp_data++;
+ tmp_size--;
+ }
+ else
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+ }
+ } while(tmp_size != 0U);
+
+ if(status == HAL_OK)
+ {
+ if(HAL_IS_BIT_SET(hswpmi->Instance->ISR, SWPMI_FLAG_RXBFF))
+ {
+ /* Clear RXBFF at end of reception */
+ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_RXBFF);
+ }
+
+ /* Check if a non-blocking transmit Process is ongoing or not */
+ if(hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX;
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+ }
+
+ if((status != HAL_OK) && (status != HAL_BUSY))
+ {
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+ }
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+
+ return status;
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with interrupt.
+ * @param hswpmi pointer to a SWPMI_HandleTypeDef structure that contains
+ * the configuration information for SWPMI module.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SWPMI_Transmit_IT(SWPMI_HandleTypeDef *hswpmi, uint32_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SWPMI_StateTypeDef tmp_state;
+
+ if((pData == NULL ) || (Size == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Process Locked */
+ __HAL_LOCK(hswpmi);
+
+ tmp_state = hswpmi->State;
+ if((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_RX))
+ {
+ /* Update handle */
+ hswpmi->pTxBuffPtr = pData;
+ hswpmi->TxXferSize = Size;
+ hswpmi->TxXferCount = Size;
+ hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE;
+
+ /* Check if a receive process is ongoing or not */
+ if(tmp_state == HAL_SWPMI_STATE_READY)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX;
+
+ /* Enable SWPMI peripheral if not */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX;
+ }
+
+ /* Enable the SWPMI transmit underrun error */
+ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_TXUNRIE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+
+ /* Enable the SWPMI interrupts: */
+ /* - Transmit data register empty */
+ /* - Transmit buffer empty */
+ /* - Transmit/Reception completion */
+ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_TIE | SWPMI_IT_TXBEIE | SWPMI_IT_TCIE);
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with interrupt.
+ * @param hswpmi SWPMI handle
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SWPMI_Receive_IT(SWPMI_HandleTypeDef *hswpmi, uint32_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SWPMI_StateTypeDef tmp_state;
+
+ if((pData == NULL ) || (Size == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Process Locked */
+ __HAL_LOCK(hswpmi);
+
+ tmp_state = hswpmi->State;
+ if((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX))
+ {
+ /* Update handle */
+ hswpmi->pRxBuffPtr = pData;
+ hswpmi->RxXferSize = Size;
+ hswpmi->RxXferCount = Size;
+ hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE;
+
+ /* Check if a transmit process is ongoing or not */
+ if(tmp_state == HAL_SWPMI_STATE_READY)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_RX;
+
+ /* Enable SWPMI peripheral if not */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+
+ /* Enable the SWPMI slave resume */
+ /* Enable the SWPMI Data Register not empty Interrupt, receive CRC Error, receive overrun and RxBuf Interrupt */
+ /* Enable the SWPMI Transmit/Reception completion */
+ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_RIE | SWPMI_IT_RXBERIE | SWPMI_IT_RXOVRIE | SWPMI_IT_RXBFIE);
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with DMA interrupt.
+ * @param hswpmi SWPMI handle
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SWPMI_Transmit_DMA(SWPMI_HandleTypeDef *hswpmi, uint32_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SWPMI_StateTypeDef tmp_state;
+
+ if((pData == NULL ) || (Size == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Process Locked */
+ __HAL_LOCK(hswpmi);
+
+ tmp_state = hswpmi->State;
+ if((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_RX))
+ {
+ /* Update handle */
+ hswpmi->pTxBuffPtr = pData;
+ hswpmi->TxXferSize = Size;
+ hswpmi->TxXferCount = Size;
+ hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE;
+
+ /* Check if a receive process is ongoing or not */
+ if(tmp_state == HAL_SWPMI_STATE_READY)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX;
+
+ /* Enable SWPMI peripheral if not */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX;
+ }
+
+ /* Set the SWPMI DMA transfer complete callback */
+ hswpmi->hdmatx->XferCpltCallback = SWPMI_DMATransmitCplt;
+
+ /* Set the SWPMI DMA Half transfer complete callback */
+ hswpmi->hdmatx->XferHalfCpltCallback = SWPMI_DMATxHalfCplt;
+
+ /* Set the DMA error callback */
+ hswpmi->hdmatx->XferErrorCallback = SWPMI_DMAError;
+
+ /* Enable the SWPMI transmit DMA stream */
+ if(HAL_DMA_Start_IT(hswpmi->hdmatx, (uint32_t)hswpmi->pTxBuffPtr, (uint32_t)&hswpmi->Instance->TDR, Size) != HAL_OK)
+ {
+ hswpmi->State = tmp_state; /* Back to previous state */
+ hswpmi->ErrorCode = HAL_SWPMI_ERROR_DMA;
+ status = HAL_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+
+ /* Enable the SWPMI transmit underrun error */
+ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_TXUNRIE);
+
+ /* Enable the DMA transfer for transmit request by setting the TXDMA bit
+ in the SWPMI CR register */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_TXDMA);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA interrupt.
+ * @param hswpmi SWPMI handle
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SWPMI_Receive_DMA(SWPMI_HandleTypeDef *hswpmi, uint32_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SWPMI_StateTypeDef tmp_state;
+
+ if((pData == NULL ) || (Size == 0U))
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Process Locked */
+ __HAL_LOCK(hswpmi);
+
+ tmp_state = hswpmi->State;
+ if((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX))
+ {
+ /* Update handle */
+ hswpmi->pRxBuffPtr = pData;
+ hswpmi->RxXferSize = Size;
+ hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE;
+
+ /* Check if a transmit process is ongoing or not */
+ if(tmp_state == HAL_SWPMI_STATE_READY)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_RX;
+
+ /* Enable SWPMI peripheral if not */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX;
+ }
+
+ /* Set the SWPMI DMA transfer complete callback */
+ hswpmi->hdmarx->XferCpltCallback = SWPMI_DMAReceiveCplt;
+
+ /* Set the SWPMI DMA Half transfer complete callback */
+ hswpmi->hdmarx->XferHalfCpltCallback = SWPMI_DMARxHalfCplt;
+
+ /* Set the DMA error callback */
+ hswpmi->hdmarx->XferErrorCallback = SWPMI_DMAError;
+
+ /* Enable the DMA request */
+ if(HAL_DMA_Start_IT(hswpmi->hdmarx, (uint32_t)&hswpmi->Instance->RDR, (uint32_t)hswpmi->pRxBuffPtr, Size) != HAL_OK)
+ {
+ hswpmi->State = tmp_state; /* Back to previous state */
+ hswpmi->ErrorCode = HAL_SWPMI_ERROR_DMA;
+ status = HAL_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+
+ /* Enable the SWPMI receive CRC Error and receive overrun interrupts */
+ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_RXBERIE | SWPMI_IT_RXOVRIE);
+
+ /* Enable the DMA transfer for the receiver request by setting the RXDMA bit
+ in the SWPMI CR register */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_RXDMA);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Stop all DMA transfers.
+ * @param hswpmi SWPMI handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SWPMI_DMAStop(SWPMI_HandleTypeDef *hswpmi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hswpmi);
+
+ /* Disable the SWPMI Tx/Rx DMA requests */
+ CLEAR_BIT(hswpmi->Instance->CR, (SWPMI_CR_TXDMA | SWPMI_CR_RXDMA));
+
+ /* Abort the SWPMI DMA tx stream */
+ if(hswpmi->hdmatx != NULL)
+ {
+ if(HAL_DMA_Abort(hswpmi->hdmatx) != HAL_OK)
+ {
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_DMA;
+ status = HAL_ERROR;
+ }
+ }
+ /* Abort the SWPMI DMA rx stream */
+ if(hswpmi->hdmarx != NULL)
+ {
+ if(HAL_DMA_Abort(hswpmi->hdmarx) != HAL_OK)
+ {
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_DMA;
+ status = HAL_ERROR;
+ }
+ }
+
+ /* Disable SWPMI interface */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+
+ return status;
+}
+
+
+/**
+ * @brief Enable the Loopback mode.
+ * @param hswpmi SWPMI handle
+ * @note Loopback mode is to be used only for test purposes
+ * @retval HAL_OK / HAL_BUSY
+ */
+HAL_StatusTypeDef HAL_SWPMI_EnableLoopback(SWPMI_HandleTypeDef *hswpmi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hswpmi);
+
+ /* Make sure the SWPMI interface is not enabled to set the loopback mode */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+
+ /* Set Loopback */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_LPBK);
+
+ /* Enable SWPMI interface in loopback mode */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+
+ return status;
+}
+
+/**
+ * @brief Disable the Loopback mode.
+ * @param hswpmi SWPMI handle
+ * @note Loopback mode is to be used only for test purposes
+ * @retval HAL_OK / HAL_BUSY
+ */
+HAL_StatusTypeDef HAL_SWPMI_DisableLoopback(SWPMI_HandleTypeDef *hswpmi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hswpmi);
+
+ /* Make sure the SWPMI interface is not enabled to reset the loopback mode */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+
+ /* Reset Loopback */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_LPBK);
+
+ /* Re-enable SWPMI interface in normal mode */
+ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hswpmi);
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SWPMI_Exported_Group3 SWPMI IRQ handler and callbacks
+ * @brief SWPMI IRQ handler.
+ *
+@verbatim
+ ==============================================================================
+ ##### SWPMI IRQ handler and callbacks #####
+ ==============================================================================
+[..] This section provides SWPMI IRQ handler and callback functions called within
+ the IRQ handler.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Handle SWPMI interrupt request.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+void HAL_SWPMI_IRQHandler(SWPMI_HandleTypeDef *hswpmi)
+{
+ uint32_t regisr = READ_REG(hswpmi->Instance->ISR);
+ uint32_t regier = READ_REG(hswpmi->Instance->IER);
+ uint32_t errcode = HAL_SWPMI_ERROR_NONE;
+
+ /* SWPMI CRC error interrupt occurred --------------------------------------*/
+ if(((regisr & SWPMI_FLAG_RXBERF) != 0U) && ((regier & SWPMI_IT_RXBERIE) != 0U))
+ {
+ /* Disable Receive CRC interrupt */
+ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_RXBERIE | SWPMI_IT_RXBFIE);
+ /* Clear Receive CRC and Receive buffer full flag */
+ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_RXBERF | SWPMI_FLAG_RXBFF);
+
+ errcode |= HAL_SWPMI_ERROR_CRC;
+ }
+
+ /* SWPMI Over-Run interrupt occurred -----------------------------------------*/
+ if(((regisr & SWPMI_FLAG_RXOVRF) != 0U) && ((regier & SWPMI_IT_RXOVRIE) != 0U))
+ {
+ /* Disable Receive overrun interrupt */
+ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_RXOVRIE);
+ /* Clear Receive overrun flag */
+ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_RXOVRF);
+
+ errcode |= HAL_SWPMI_ERROR_OVR;
+ }
+
+ /* SWPMI Under-Run interrupt occurred -----------------------------------------*/
+ if(((regisr & SWPMI_FLAG_TXUNRF) != 0U) && ((regier & SWPMI_IT_TXUNRIE) != 0U))
+ {
+ /* Disable Transmit under run interrupt */
+ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_TXUNRIE);
+ /* Clear Transmit under run flag */
+ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_TXUNRF);
+
+ errcode |= HAL_SWPMI_ERROR_UDR;
+ }
+
+ /* Call SWPMI Error Call back function if needed --------------------------*/
+ if(errcode != HAL_SWPMI_ERROR_NONE)
+ {
+ hswpmi->ErrorCode |= errcode;
+
+ if((errcode & HAL_SWPMI_ERROR_UDR) != 0U)
+ {
+ /* Check TXDMA transfer to abort */
+ if(HAL_IS_BIT_SET(hswpmi->Instance->CR, SWPMI_CR_TXDMA))
+ {
+ /* Disable DMA TX at SWPMI level */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_TXDMA);
+
+ /* Abort the USART DMA Tx stream */
+ if(hswpmi->hdmatx != NULL)
+ {
+ /* Set the SWPMI Tx DMA Abort callback :
+ will lead to call HAL_SWPMI_ErrorCallback() at end of DMA abort procedure */
+ hswpmi->hdmatx->XferAbortCallback = SWPMI_DMAAbortOnError;
+ /* Abort DMA TX */
+ if(HAL_DMA_Abort_IT(hswpmi->hdmatx) != HAL_OK)
+ {
+ /* Call Directly hswpmi->hdmatx->XferAbortCallback function in case of error */
+ hswpmi->hdmatx->XferAbortCallback(hswpmi->hdmatx);
+ }
+ }
+ else
+ {
+ /* Set the SWPMI state ready to be able to start again the process */
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->ErrorCallback(hswpmi);
+#else
+ HAL_SWPMI_ErrorCallback(hswpmi);
+#endif
+ }
+ }
+ else
+ {
+ /* Set the SWPMI state ready to be able to start again the process */
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->ErrorCallback(hswpmi);
+#else
+ HAL_SWPMI_ErrorCallback(hswpmi);
+#endif
+ }
+ }
+ else
+ {
+ /* Check RXDMA transfer to abort */
+ if(HAL_IS_BIT_SET(hswpmi->Instance->CR, SWPMI_CR_RXDMA))
+ {
+ /* Disable DMA RX at SWPMI level */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_RXDMA);
+
+ /* Abort the USART DMA Rx stream */
+ if(hswpmi->hdmarx != NULL)
+ {
+ /* Set the SWPMI Rx DMA Abort callback :
+ will lead to call HAL_SWPMI_ErrorCallback() at end of DMA abort procedure */
+ hswpmi->hdmarx->XferAbortCallback = SWPMI_DMAAbortOnError;
+ /* Abort DMA RX */
+ if(HAL_DMA_Abort_IT(hswpmi->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hswpmi->hdmarx->XferAbortCallback function in case of error */
+ hswpmi->hdmarx->XferAbortCallback(hswpmi->hdmarx);
+ }
+ }
+ else
+ {
+ /* Set the SWPMI state ready to be able to start again the process */
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->ErrorCallback(hswpmi);
+#else
+ HAL_SWPMI_ErrorCallback(hswpmi);
+#endif
+ }
+ }
+ else
+ {
+ /* Set the SWPMI state ready to be able to start again the process */
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->ErrorCallback(hswpmi);
+#else
+ HAL_SWPMI_ErrorCallback(hswpmi);
+#endif
+ }
+ }
+ }
+
+ /* SWPMI in mode Receiver ---------------------------------------------------*/
+ if(((regisr & SWPMI_FLAG_RXNE) != 0U) && ((regier & SWPMI_IT_RIE) != 0U))
+ {
+ SWPMI_Receive_IT(hswpmi);
+ }
+
+ /* SWPMI in mode Transmitter ------------------------------------------------*/
+ if(((regisr & SWPMI_FLAG_TXE) != 0U) && ((regier & SWPMI_IT_TIE) != 0U))
+ {
+ SWPMI_Transmit_IT(hswpmi);
+ }
+
+ /* SWPMI in mode Transmitter (Transmit buffer empty) ------------------------*/
+ if(((regisr & SWPMI_FLAG_TXBEF) != 0U) && ((regier & SWPMI_IT_TXBEIE) != 0U))
+ {
+ SWPMI_EndTransmit_IT(hswpmi);
+ }
+
+ /* SWPMI in mode Receiver (Receive buffer full) -----------------------------*/
+ if(((regisr & SWPMI_FLAG_RXBFF) != 0U) && ((regier & SWPMI_IT_RXBFIE) != 0U))
+ {
+ SWPMI_EndReceive_IT(hswpmi);
+ }
+
+ /* Both Transmission and reception complete ---------------------------------*/
+ if(((regisr & SWPMI_FLAG_TCF) != 0U) && ((regier & SWPMI_IT_TCIE) != 0U))
+ {
+ SWPMI_EndTransmitReceive_IT(hswpmi);
+ }
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+__weak void HAL_SWPMI_TxCpltCallback(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hswpmi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SWPMI_TxCpltCallback is to be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+__weak void HAL_SWPMI_TxHalfCpltCallback(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hswpmi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_SWPMI_TxHalfCpltCallback is to be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+__weak void HAL_SWPMI_RxCpltCallback(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hswpmi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SWPMI_RxCpltCallback is to be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Half Transfer completed callback.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+__weak void HAL_SWPMI_RxHalfCpltCallback(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hswpmi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_SWPMI_RxHalfCpltCallback is to be implemented in the user file
+ */
+}
+
+/**
+ * @brief SWPMI error callback.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+__weak void HAL_SWPMI_ErrorCallback(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hswpmi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SWPMI_ErrorCallback is to be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SWPMI_Exported_Group4 Peripheral Control methods
+ * @brief SWPMI control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control methods #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the SWPMI.
+ (+) HAL_SWPMI_GetState() API is helpful to check in run-time the state of the SWPMI peripheral
+ (+) HAL_SWPMI_GetError() API is helpful to check in run-time the error state of the SWPMI peripheral
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the SWPMI handle state.
+ * @param hswpmi SWPMI handle
+ * @retval HAL state
+ */
+HAL_SWPMI_StateTypeDef HAL_SWPMI_GetState(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Return SWPMI handle state */
+ return hswpmi->State;
+}
+
+/**
+* @brief Return the SWPMI error code.
+* @param hswpmi : pointer to a SWPMI_HandleTypeDef structure that contains
+ * the configuration information for the specified SWPMI.
+* @retval SWPMI Error Code
+*/
+uint32_t HAL_SWPMI_GetError(SWPMI_HandleTypeDef *hswpmi)
+{
+ return hswpmi->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup SWPMI_Private_Functions SWPMI Private Functions
+ * @{
+ */
+
+/**
+ * @brief Transmit an amount of data in interrupt mode.
+ * @note Function called under interruption only, once interruptions have been enabled by HAL_SWPMI_Transmit_IT()
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+static void SWPMI_Transmit_IT(SWPMI_HandleTypeDef *hswpmi)
+{
+ HAL_SWPMI_StateTypeDef tmp_state = hswpmi->State;
+
+ if ((tmp_state == HAL_SWPMI_STATE_BUSY_TX) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX_RX))
+ {
+ if(hswpmi->TxXferCount == 0U)
+ {
+ /* Disable the SWPMI TXE and Underrun Interrupts */
+ CLEAR_BIT(hswpmi->Instance->IER, (SWPMI_IT_TIE | SWPMI_IT_TXUNRIE));
+ }
+ else
+ {
+ hswpmi->Instance->TDR = (uint32_t)*hswpmi->pTxBuffPtr;
+ hswpmi->pTxBuffPtr++;
+ hswpmi->TxXferCount--;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+}
+
+/**
+ * @brief Wraps up transmission in non-blocking mode.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+static void SWPMI_EndTransmit_IT(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Clear the SWPMI Transmit buffer empty Flag */
+ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_TXBEF);
+ /* Disable the all SWPMI Transmit Interrupts */
+ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_TIE | SWPMI_IT_TXUNRIE | SWPMI_IT_TXBEIE);
+
+ /* Check if a receive Process is ongoing or not */
+ if(hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_RX;
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+ }
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->TxCpltCallback(hswpmi);
+#else
+ HAL_SWPMI_TxCpltCallback(hswpmi);
+#endif
+}
+
+/**
+ * @brief Receive an amount of data in interrupt mode.
+ * @note Function called under interruption only, once interruptions have been enabled by HAL_SWPMI_Receive_IT()
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+static void SWPMI_Receive_IT(SWPMI_HandleTypeDef *hswpmi)
+{
+ HAL_SWPMI_StateTypeDef tmp_state = hswpmi->State;
+
+ if((tmp_state == HAL_SWPMI_STATE_BUSY_RX) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX_RX))
+ {
+ *hswpmi->pRxBuffPtr = (uint32_t)(hswpmi->Instance->RDR);
+ hswpmi->pRxBuffPtr++;
+
+ --hswpmi->RxXferCount;
+ if(hswpmi->RxXferCount == 0U)
+ {
+ /* Wait for RXBFF flag to update state */
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->RxCpltCallback(hswpmi);
+#else
+ HAL_SWPMI_RxCpltCallback(hswpmi);
+#endif
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+}
+
+/**
+ * @brief Wraps up reception in non-blocking mode.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+static void SWPMI_EndReceive_IT(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Clear the SWPMI Receive buffer full Flag */
+ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_RXBFF);
+ /* Disable the all SWPMI Receive Interrupts */
+ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_RIE | SWPMI_IT_RXBERIE | SWPMI_IT_RXOVRIE | SWPMI_IT_RXBFIE);
+
+ /* Check if a transmit Process is ongoing or not */
+ if(hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX;
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+ }
+}
+
+/**
+ * @brief Wraps up transmission and reception in non-blocking mode.
+ * @param hswpmi SWPMI handle
+ * @retval None
+ */
+static void SWPMI_EndTransmitReceive_IT(SWPMI_HandleTypeDef *hswpmi)
+{
+ /* Clear the SWPMI Transmission Complete Flag */
+ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_TCF);
+ /* Disable the SWPMI Transmission Complete Interrupt */
+ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_TCIE);
+
+ /* Check if a receive Process is ongoing or not */
+ if(hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_RX;
+ }
+ else if(hswpmi->State == HAL_SWPMI_STATE_BUSY_TX)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+}
+
+/**
+ * @brief DMA SWPMI transmit process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SWPMI_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ SWPMI_HandleTypeDef* hswpmi = ( SWPMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ uint32_t tickstart;
+
+ /* DMA Normal mode*/
+ if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & DMA_SxCR_CIRC) == 0U)
+ {
+ hswpmi->TxXferCount = 0U;
+
+ /* Disable the DMA transfer for transmit request by setting the TXDMA bit
+ in the SWPMI CR register */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_TXDMA);
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Wait the TXBEF */
+ if(SWPMI_WaitOnFlagSetUntilTimeout(hswpmi, SWPMI_FLAG_TXBEF, tickstart, SWPMI_TIMEOUT_VALUE) != HAL_OK)
+ {
+ /* Timeout occurred */
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_TXBEF_TIMEOUT;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->ErrorCallback(hswpmi);
+#else
+ HAL_SWPMI_ErrorCallback(hswpmi);
+#endif
+ }
+ else
+ {
+ /* No Timeout */
+ /* Check if a receive process is ongoing or not */
+ if(hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_RX;
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+ }
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->TxCpltCallback(hswpmi);
+#else
+ HAL_SWPMI_TxCpltCallback(hswpmi);
+#endif
+ }
+ }
+ /* DMA Circular mode */
+ else
+ {
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->TxCpltCallback(hswpmi);
+#else
+ HAL_SWPMI_TxCpltCallback(hswpmi);
+#endif
+ }
+}
+
+/**
+ * @brief DMA SWPMI transmit process half complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SWPMI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ SWPMI_HandleTypeDef* hswpmi = (SWPMI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->TxHalfCpltCallback(hswpmi);
+#else
+ HAL_SWPMI_TxHalfCpltCallback(hswpmi);
+#endif
+}
+
+
+/**
+ * @brief DMA SWPMI receive process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SWPMI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SWPMI_HandleTypeDef* hswpmi = ( SWPMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* DMA Normal mode*/
+ if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & DMA_SxCR_CIRC) == 0U)
+ {
+ hswpmi->RxXferCount = 0U;
+
+ /* Disable the DMA transfer for the receiver request by setting the RXDMA bit
+ in the SWPMI CR register */
+ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_RXDMA);
+
+ /* Check if a transmit Process is ongoing or not */
+ if(hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX)
+ {
+ hswpmi->State = HAL_SWPMI_STATE_BUSY_TX;
+ }
+ else
+ {
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+ }
+ }
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->RxCpltCallback(hswpmi);
+#else
+ HAL_SWPMI_RxCpltCallback(hswpmi);
+#endif
+}
+
+/**
+ * @brief DMA SWPMI receive process half complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SWPMI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ SWPMI_HandleTypeDef* hswpmi = (SWPMI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->RxHalfCpltCallback(hswpmi);
+#else
+ HAL_SWPMI_RxHalfCpltCallback(hswpmi);
+#endif
+}
+
+/**
+ * @brief DMA SWPMI communication error callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SWPMI_DMAError(DMA_HandleTypeDef *hdma)
+{
+ SWPMI_HandleTypeDef* hswpmi = ( SWPMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Update handle */
+ hswpmi->RxXferCount = 0U;
+ hswpmi->TxXferCount = 0U;
+ hswpmi->State= HAL_SWPMI_STATE_READY;
+ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_DMA;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->ErrorCallback(hswpmi);
+#else
+ HAL_SWPMI_ErrorCallback(hswpmi);
+#endif
+}
+
+/**
+ * @brief DMA SWPMI communication abort callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void SWPMI_DMAAbortOnError(DMA_HandleTypeDef *hdma)
+{
+ SWPMI_HandleTypeDef* hswpmi = ( SWPMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Update handle */
+ hswpmi->RxXferCount = 0U;
+ hswpmi->TxXferCount = 0U;
+ hswpmi->State= HAL_SWPMI_STATE_READY;
+
+#if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1)
+ hswpmi->ErrorCallback(hswpmi);
+#else
+ HAL_SWPMI_ErrorCallback(hswpmi);
+#endif
+}
+
+/**
+ * @brief Handle SWPMI Communication Timeout.
+ * @param hswpmi SWPMI handle
+ * @param Flag: specifies the SWPMI flag to check.
+ * @param Tickstart Tick start value
+ * @param Timeout timeout duration.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SWPMI_WaitOnFlagSetUntilTimeout(SWPMI_HandleTypeDef *hswpmi, uint32_t Flag, uint32_t Tickstart, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Wait until flag is set */
+ while(!(HAL_IS_BIT_SET(hswpmi->Instance->ISR, Flag)))
+ {
+ /* Check for the Timeout */
+ if ((((HAL_GetTick() - Tickstart) > Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ /* Set the SWPMI state ready to be able to start again the process */
+ hswpmi->State = HAL_SWPMI_STATE_READY;
+
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SWPMI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_tim.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_tim.c
new file mode 100644
index 0000000000..1885d04b39
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_tim.c
@@ -0,0 +1,7047 @@
+/**
+ ******************************************************************************
+ * @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
+ @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 @ref HAL_TIM_RegisterCallback() to register a callback.
+ @ref HAL_TIM_RegisterCallback() takes as parameters the HAL peripheral handle,
+ the Callback ID and a pointer to the user callback function.
+
+ [..]
+ Use function @ref HAL_TIM_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ @ref 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 @ref HAL_TIM_TriggerCallback(), @ref 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 @ref 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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup TIM_Private_Functions
+ * @{
+ */
+static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config);
+static void TIM_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_DMATriggerCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMATriggerHalfCplt(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+ 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_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 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 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));
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Change the TIM state*/
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Base generation.
+ * @param htim TIM Base handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the TIM state*/
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Base generation in interrupt mode.
+ * @param htim TIM 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));
+
+ /* 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 */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __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);
+
+ /* 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, uint32_t *pData, uint16_t Length)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_DMA_INSTANCE(htim->Instance));
+
+ if (htim->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if ((pData == NULL) && (Length > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+ /* 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 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 */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __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);
+
+ /* Change the htim 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_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 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 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));
+
+ /* 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 */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __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);
+
+ /* 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)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Enable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Enable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation in interrupt mode.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Disable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Output Compare signal generation in DMA mode.
+ * @param htim 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, uint32_t *pData, uint16_t Length)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ if (htim->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if ((pData == NULL) && (Length > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+ 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 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 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 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 HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Enable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation in DMA mode.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (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:
+ break;
+ }
+
+ /* Disable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group3 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_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 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 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));
+
+ /* 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 */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __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);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the PWM signal generation in interrupt mode.
+ * @param htim TIM 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)
+{
+ uint32_t tmpsmcr;
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Enable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Disable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM PWM signal generation in DMA mode.
+ * @param htim 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, uint32_t *pData, uint16_t Length)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ if (htim->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if ((pData == NULL) && (Length > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+ 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 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 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 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 HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Disable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group4 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_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 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 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;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ /* Enable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Input Capture measurement.
+ * @param htim TIM Input Capture handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ /* Disable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* 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)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Enable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ break;
+ }
+ /* Enable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Disable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Input Capture measurement 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)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+ assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+ if (htim->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if ((pData == NULL) && (Length > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+ 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 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 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 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 HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Enable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+ assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (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:
+ break;
+ }
+
+ /* Disable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group5 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()
+ * @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_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 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 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.
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* Enable the Capture compare and the Input Capture channels
+ (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+ if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+ if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+ in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together
+
+ No need to enable the counter, it's enabled automatically by hardware
+ (the counter starts in response to a stimulus and generate a pulse */
+
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM One Pulse signal generation.
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel TIM Channels to be disable
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* Disable the Capture compare and the Input Capture channels
+ (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+ if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+ if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+ in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */
+
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM One Pulse signal generation in interrupt mode.
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* Enable the Capture compare and the Input Capture channels
+ (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+ if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+ if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+ in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together
+
+ No need to enable the counter, it's enabled automatically by hardware
+ (the counter starts in response to a stimulus and generate a pulse */
+
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM One Pulse signal generation in interrupt mode.
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+
+ /* Disable the Capture compare and the Input Capture channels
+ (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+ if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+ if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+ in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* 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
+ * @param htim TIM Encoder Interface handle
+ * @param sConfig TIM Encoder Interface configuration structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim, TIM_Encoder_InitTypeDef *sConfig)
+{
+ uint32_t tmpsmcr;
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Check the TIM handle allocation */
+ if (htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+ assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+ assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+ assert_param(IS_TIM_ENCODER_MODE(sConfig->EncoderMode));
+ assert_param(IS_TIM_IC_SELECTION(sConfig->IC1Selection));
+ assert_param(IS_TIM_IC_SELECTION(sConfig->IC2Selection));
+ assert_param(IS_TIM_ENCODERINPUT_POLARITY(sConfig->IC1Polarity));
+ assert_param(IS_TIM_ENCODERINPUT_POLARITY(sConfig->IC2Polarity));
+ assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler));
+ assert_param(IS_TIM_IC_PRESCALER(sConfig->IC2Prescaler));
+ assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter));
+ assert_param(IS_TIM_IC_FILTER(sConfig->IC2Filter));
+
+ 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 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 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Enable the encoder interface channels */
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ break;
+ }
+
+ default :
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ break;
+ }
+ }
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Encoder Interface.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_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);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Encoder Interface in interrupt mode.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Enable the encoder interface channels */
+ /* Enable the capture compare Interrupts 1 and/or 2 */
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ default :
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+ }
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Encoder Interface in interrupt mode.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_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);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Encoder Interface in DMA mode.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @param pData1 The destination Buffer address for IC1.
+ * @param pData2 The destination Buffer address for IC2.
+ * @param Length The length of data to be transferred from TIM peripheral to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1,
+ uint32_t *pData2, uint16_t Length)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+ if (htim->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if ((((pData1 == NULL) || (pData2 == NULL))) && (Length > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+ 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 HAL_ERROR;
+ }
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA 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 HAL_ERROR;
+ }
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ break;
+ }
+
+ case TIM_CHANNEL_ALL:
+ {
+ /* Set the DMA 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 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 HAL_ERROR;
+ }
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ break;
+ }
+
+ default:
+ break;
+ }
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Encoder Interface in DMA mode.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_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);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+/** @defgroup TIM_Exported_Functions_Group7 TIM IRQ handler management
+ * @brief TIM IRQ handler management
+ *
+@verbatim
+ ==============================================================================
+ ##### IRQ handler management #####
+ ==============================================================================
+ [..]
+ This section provides Timer IRQ handler function.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief This function handles TIM interrupts requests.
+ * @param htim TIM handle
+ * @retval None
+ */
+void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
+{
+ /* Capture compare 1 event */
+ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) != RESET)
+ {
+ {
+ __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+ /* Input capture event */
+ if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureCallback(htim);
+#else
+ HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ /* Output compare event */
+ else
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->OC_DelayElapsedCallback(htim);
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+ }
+ }
+ }
+ /* Capture compare 2 event */
+ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) != RESET)
+ {
+ __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ /* Input capture event */
+ if ((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureCallback(htim);
+#else
+ HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ /* Output compare event */
+ else
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->OC_DelayElapsedCallback(htim);
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+ }
+ }
+ /* Capture compare 3 event */
+ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) != RESET)
+ {
+ __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ /* Input capture event */
+ if ((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U)
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureCallback(htim);
+#else
+ HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ /* Output compare event */
+ else
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->OC_DelayElapsedCallback(htim);
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+ }
+ }
+ /* Capture compare 4 event */
+ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) != RESET)
+ {
+ __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+ /* Input capture event */
+ if ((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U)
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureCallback(htim);
+#else
+ HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ /* Output compare event */
+ else
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->OC_DelayElapsedCallback(htim);
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+ }
+ }
+ /* TIM Update event */
+ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET)
+ {
+ __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->PeriodElapsedCallback(htim);
+#else
+ HAL_TIM_PeriodElapsedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+ /* TIM Break input event */
+ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) != RESET)
+ {
+ __HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->BreakCallback(htim);
+#else
+ HAL_TIMEx_BreakCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+ /* TIM Break2 input event */
+ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK2) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) != RESET)
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_BREAK2);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->Break2Callback(htim);
+#else
+ HAL_TIMEx_Break2Callback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+ /* TIM Trigger detection event */
+ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) != RESET)
+ {
+ __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->TriggerCallback(htim);
+#else
+ HAL_TIM_TriggerCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+ /* TIM commutation event */
+ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) != RESET)
+ {
+ __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->CommutationCallback(htim);
+#else
+ HAL_TIMEx_CommutCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group8 TIM Peripheral Control functions
+ * @brief TIM Peripheral Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Configure The Input Output channels for OC, PWM, IC or One Pulse mode.
+ (+) Configure External Clock source.
+ (+) Configure Complementary channels, break features and dead time.
+ (+) Configure Master and the Slave synchronization.
+ (+) Configure the DMA Burst Mode.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM Output Compare Channels according to the specified
+ * parameters in the TIM_OC_InitTypeDef.
+ * @param htim TIM Output Compare handle
+ * @param sConfig TIM Output Compare configuration structure
+ * @param Channel TIM Channels to configure
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim,
+ TIM_OC_InitTypeDef *sConfig,
+ uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CHANNELS(Channel));
+ assert_param(IS_TIM_OC_MODE(sConfig->OCMode));
+ assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 1 in Output Compare */
+ TIM_OC1_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 2 in Output Compare */
+ TIM_OC2_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 3 in Output Compare */
+ TIM_OC3_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 4 in Output Compare */
+ TIM_OC4_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_5:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC5_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 5 in Output Compare */
+ TIM_OC5_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_6:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC6_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 6 in Output Compare */
+ TIM_OC6_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM 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, TIM_IC_InitTypeDef *sConfig, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_IC_POLARITY(sConfig->ICPolarity));
+ assert_param(IS_TIM_IC_SELECTION(sConfig->ICSelection));
+ assert_param(IS_TIM_IC_PRESCALER(sConfig->ICPrescaler));
+ assert_param(IS_TIM_IC_FILTER(sConfig->ICFilter));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ if (Channel == TIM_CHANNEL_1)
+ {
+ /* TI1 Configuration */
+ TIM_TI1_SetConfig(htim->Instance,
+ sConfig->ICPolarity,
+ sConfig->ICSelection,
+ sConfig->ICFilter);
+
+ /* Reset the IC1PSC Bits */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+
+ /* Set the IC1PSC value */
+ htim->Instance->CCMR1 |= sConfig->ICPrescaler;
+ }
+ else if (Channel == TIM_CHANNEL_2)
+ {
+ /* TI2 Configuration */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ TIM_TI2_SetConfig(htim->Instance,
+ sConfig->ICPolarity,
+ sConfig->ICSelection,
+ sConfig->ICFilter);
+
+ /* Reset the IC2PSC Bits */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC;
+
+ /* Set the IC2PSC value */
+ htim->Instance->CCMR1 |= (sConfig->ICPrescaler << 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
+ {
+ /* 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);
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM PWM channels according to the specified
+ * parameters in the TIM_OC_InitTypeDef.
+ * @param htim TIM PWM handle
+ * @param sConfig TIM PWM configuration structure
+ * @param Channel TIM Channels to be configured
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
+ TIM_OC_InitTypeDef *sConfig,
+ uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CHANNELS(Channel));
+ assert_param(IS_TIM_PWM_MODE(sConfig->OCMode));
+ assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity));
+ assert_param(IS_TIM_FAST_STATE(sConfig->OCFastMode));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+ /* Configure the Channel 1 in PWM mode */
+ TIM_OC1_SetConfig(htim->Instance, sConfig);
+
+ /* Set the Preload enable bit for channel1 */
+ htim->Instance->CCMR1 |= TIM_CCMR1_OC1PE;
+
+ /* Configure the Output Fast mode */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE;
+ htim->Instance->CCMR1 |= sConfig->OCFastMode;
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ /* Configure the Channel 2 in PWM mode */
+ TIM_OC2_SetConfig(htim->Instance, sConfig);
+
+ /* Set the Preload enable bit for channel2 */
+ htim->Instance->CCMR1 |= TIM_CCMR1_OC2PE;
+
+ /* Configure the Output Fast mode */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2FE;
+ htim->Instance->CCMR1 |= sConfig->OCFastMode << 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:
+ break;
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM One Pulse Channels according to the specified
+ * parameters in the TIM_OnePulse_InitTypeDef.
+ * @param htim TIM One Pulse handle
+ * @param sConfig TIM One Pulse configuration structure
+ * @param OutputChannel TIM 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)
+{
+ 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:
+ break;
+ }
+
+ switch (InputChannel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+ TIM_TI1_SetConfig(htim->Instance, sConfig->ICPolarity,
+ sConfig->ICSelection, sConfig->ICFilter);
+
+ /* Reset the IC1PSC Bits */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+
+ /* Select the Trigger source */
+ htim->Instance->SMCR &= ~TIM_SMCR_TS;
+ htim->Instance->SMCR |= TIM_TS_TI1FP1;
+
+ /* Select the Slave Mode */
+ htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+ htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER;
+ break;
+ }
+ case TIM_CHANNEL_2:
+ {
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ TIM_TI2_SetConfig(htim->Instance, sConfig->ICPolarity,
+ sConfig->ICSelection, sConfig->ICFilter);
+
+ /* Reset the IC2PSC Bits */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC;
+
+ /* Select the Trigger source */
+ htim->Instance->SMCR &= ~TIM_SMCR_TS;
+ htim->Instance->SMCR |= TIM_TS_TI2FP2;
+
+ /* Select the Slave Mode */
+ htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+ htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the DMA Burst to transfer Data from the memory to the TIM peripheral
+ * @param htim TIM handle
+ * @param BurstBaseAddress TIM Base address from 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, uint32_t *BurstBuffer, uint32_t BurstLength)
+{
+ return HAL_TIM_DMABurst_MultiWriteStart(htim, BurstBaseAddress, BurstRequestSrc, BurstBuffer, BurstLength,
+ ((BurstLength) >> 8U) + 1U);
+}
+
+/**
+ * @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, uint32_t *BurstBuffer,
+ uint32_t BurstLength, uint32_t DataLength)
+{
+ /* 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->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if ((BurstBuffer == NULL) && (BurstLength > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_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 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 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 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 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 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 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 HAL_ERROR;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ /* Configure the DMA Burst Mode */
+ htim->Instance->DCR = (BurstBaseAddress | BurstLength);
+ /* Enable the TIM DMA Request */
+ __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM DMA Burst mode
+ * @param htim TIM handle
+ * @param BurstRequestSrc TIM DMA Request sources to disable
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc)
+{
+ 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:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+ break;
+ }
+ case TIM_DMA_CC1:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+ case TIM_DMA_CC2:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+ case TIM_DMA_CC3:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+ case TIM_DMA_CC4:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+ break;
+ }
+ case TIM_DMA_COM:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+ break;
+ }
+ case TIM_DMA_TRIGGER:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_TRIGGER]);
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (HAL_OK == status)
+ {
+ /* Disable the TIM Update DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+ }
+
+ /* 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)
+{
+ return HAL_TIM_DMABurst_MultiReadStart(htim, BurstBaseAddress, BurstRequestSrc, BurstBuffer, BurstLength,
+ ((BurstLength) >> 8U) + 1U);
+}
+
+/**
+ * @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)
+{
+ /* 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->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if ((BurstBuffer == NULL) && (BurstLength > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_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 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 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 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 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 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 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 HAL_ERROR;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ /* Configure the DMA Burst Mode */
+ htim->Instance->DCR = (BurstBaseAddress | BurstLength);
+
+ /* Enable the TIM DMA Request */
+ __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the DMA burst reading
+ * @param htim TIM handle
+ * @param BurstRequestSrc TIM DMA Request sources to disable.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc)
+{
+ 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:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+ break;
+ }
+ case TIM_DMA_CC1:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+ case TIM_DMA_CC2:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+ case TIM_DMA_CC3:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+ case TIM_DMA_CC4:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+ break;
+ }
+ case TIM_DMA_COM:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+ break;
+ }
+ case TIM_DMA_TRIGGER:
+ {
+ status = HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_TRIGGER]);
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (HAL_OK == status)
+ {
+ /* Disable the TIM Update DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+ }
+
+ /* 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,
+ TIM_ClearInputConfigTypeDef *sClearInputConfig,
+ uint32_t Channel)
+{
+ /* 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:
+ break;
+ }
+
+ 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 HAL_OK;
+}
+
+/**
+ * @brief Configures the clock source to be used
+ * @param htim TIM handle
+ * @param sClockSourceConfig pointer to a TIM_ClockConfigTypeDef structure that
+ * contains the clock source information for the TIM peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef *sClockSourceConfig)
+{
+ uint32_t tmpsmcr;
+
+ /* 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:
+ break;
+ }
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Selects the signal connected to the TI1 input: direct from CH1_input
+ * or a XOR combination between CH1_input, CH2_input & CH3_input
+ * @param htim TIM handle.
+ * @param TI1_Selection Indicate whether or not channel 1 is connected to the
+ * output of a XOR gate.
+ * This parameter can be one of the following values:
+ * @arg TIM_TI1SELECTION_CH1: The TIMx_CH1 pin is connected to TI1 input
+ * @arg TIM_TI1SELECTION_XORCOMBINATION: The TIMx_CH1, CH2 and CH3
+ * pins are connected to the TI1 input (XOR combination)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection)
+{
+ uint32_t tmpcr2;
+
+ /* 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, 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,
+ 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(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;
+ }
+ /* Process locked */
+ __HAL_LOCK(htim);
+
+ 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;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(htim);
+
+ 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;
+
+ /* Process locked */
+ __HAL_LOCK(htim);
+
+ if (htim->State == HAL_TIM_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_TIM_BASE_MSPINIT_CB_ID :
+ htim->Base_MspInitCallback = HAL_TIM_Base_MspInit; /* Legacy weak Base MspInit Callback */
+ break;
+
+ case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+ htim->Base_MspDeInitCallback = HAL_TIM_Base_MspDeInit; /* Legacy weak Base Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_IC_MSPINIT_CB_ID :
+ htim->IC_MspInitCallback = HAL_TIM_IC_MspInit; /* Legacy weak IC Msp Init Callback */
+ break;
+
+ case HAL_TIM_IC_MSPDEINIT_CB_ID :
+ htim->IC_MspDeInitCallback = HAL_TIM_IC_MspDeInit; /* Legacy weak IC Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_OC_MSPINIT_CB_ID :
+ htim->OC_MspInitCallback = HAL_TIM_OC_MspInit; /* Legacy weak OC Msp Init Callback */
+ break;
+
+ case HAL_TIM_OC_MSPDEINIT_CB_ID :
+ htim->OC_MspDeInitCallback = HAL_TIM_OC_MspDeInit; /* Legacy weak OC Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_PWM_MSPINIT_CB_ID :
+ htim->PWM_MspInitCallback = HAL_TIM_PWM_MspInit; /* Legacy weak PWM Msp Init Callback */
+ break;
+
+ case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+ htim->PWM_MspDeInitCallback = HAL_TIM_PWM_MspDeInit; /* Legacy weak PWM Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+ htim->OnePulse_MspInitCallback = HAL_TIM_OnePulse_MspInit; /* Legacy weak One Pulse Msp Init Callback */
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+ htim->OnePulse_MspDeInitCallback = HAL_TIM_OnePulse_MspDeInit; /* Legacy weak One Pulse Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+ htim->Encoder_MspInitCallback = HAL_TIM_Encoder_MspInit; /* Legacy weak Encoder Msp Init Callback */
+ break;
+
+ case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+ htim->Encoder_MspDeInitCallback = HAL_TIM_Encoder_MspDeInit; /* Legacy weak Encoder Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+ htim->HallSensor_MspInitCallback = HAL_TIMEx_HallSensor_MspInit; /* Legacy weak Hall Sensor Msp Init Callback */
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+ htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit; /* Legacy weak Hall Sensor Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_PERIOD_ELAPSED_CB_ID :
+ htim->PeriodElapsedCallback = HAL_TIM_PeriodElapsedCallback; /* Legacy weak Period Elapsed Callback */
+ break;
+
+ case HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID :
+ htim->PeriodElapsedHalfCpltCallback = HAL_TIM_PeriodElapsedHalfCpltCallback; /* Legacy weak Period Elapsed half complete Callback */
+ break;
+
+ case HAL_TIM_TRIGGER_CB_ID :
+ htim->TriggerCallback = HAL_TIM_TriggerCallback; /* Legacy weak Trigger Callback */
+ break;
+
+ case HAL_TIM_TRIGGER_HALF_CB_ID :
+ htim->TriggerHalfCpltCallback = HAL_TIM_TriggerHalfCpltCallback; /* Legacy weak Trigger half complete Callback */
+ break;
+
+ case HAL_TIM_IC_CAPTURE_CB_ID :
+ htim->IC_CaptureCallback = HAL_TIM_IC_CaptureCallback; /* Legacy weak IC Capture Callback */
+ break;
+
+ case HAL_TIM_IC_CAPTURE_HALF_CB_ID :
+ htim->IC_CaptureHalfCpltCallback = HAL_TIM_IC_CaptureHalfCpltCallback; /* Legacy weak IC Capture half complete Callback */
+ break;
+
+ case HAL_TIM_OC_DELAY_ELAPSED_CB_ID :
+ htim->OC_DelayElapsedCallback = HAL_TIM_OC_DelayElapsedCallback; /* Legacy weak OC Delay Elapsed Callback */
+ break;
+
+ case HAL_TIM_PWM_PULSE_FINISHED_CB_ID :
+ htim->PWM_PulseFinishedCallback = HAL_TIM_PWM_PulseFinishedCallback; /* Legacy weak PWM Pulse Finished Callback */
+ break;
+
+ case HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID :
+ htim->PWM_PulseFinishedHalfCpltCallback = HAL_TIM_PWM_PulseFinishedHalfCpltCallback; /* Legacy weak PWM Pulse Finished half complete Callback */
+ break;
+
+ case HAL_TIM_ERROR_CB_ID :
+ htim->ErrorCallback = HAL_TIM_ErrorCallback; /* Legacy weak Error Callback */
+ break;
+
+ case HAL_TIM_COMMUTATION_CB_ID :
+ htim->CommutationCallback = HAL_TIMEx_CommutCallback; /* Legacy weak Commutation Callback */
+ break;
+
+ case HAL_TIM_COMMUTATION_HALF_CB_ID :
+ htim->CommutationHalfCpltCallback = HAL_TIMEx_CommutHalfCpltCallback; /* Legacy weak Commutation half complete Callback */
+ break;
+
+ case HAL_TIM_BREAK_CB_ID :
+ htim->BreakCallback = HAL_TIMEx_BreakCallback; /* Legacy weak Break Callback */
+ break;
+
+ case HAL_TIM_BREAK2_CB_ID :
+ htim->Break2Callback = HAL_TIMEx_Break2Callback; /* Legacy weak Break2 Callback */
+ 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 = HAL_TIM_Base_MspInit; /* Legacy weak Base MspInit Callback */
+ break;
+
+ case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+ htim->Base_MspDeInitCallback = HAL_TIM_Base_MspDeInit; /* Legacy weak Base Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_IC_MSPINIT_CB_ID :
+ htim->IC_MspInitCallback = HAL_TIM_IC_MspInit; /* Legacy weak IC Msp Init Callback */
+ break;
+
+ case HAL_TIM_IC_MSPDEINIT_CB_ID :
+ htim->IC_MspDeInitCallback = HAL_TIM_IC_MspDeInit; /* Legacy weak IC Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_OC_MSPINIT_CB_ID :
+ htim->OC_MspInitCallback = HAL_TIM_OC_MspInit; /* Legacy weak OC Msp Init Callback */
+ break;
+
+ case HAL_TIM_OC_MSPDEINIT_CB_ID :
+ htim->OC_MspDeInitCallback = HAL_TIM_OC_MspDeInit; /* Legacy weak OC Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_PWM_MSPINIT_CB_ID :
+ htim->PWM_MspInitCallback = HAL_TIM_PWM_MspInit; /* Legacy weak PWM Msp Init Callback */
+ break;
+
+ case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+ htim->PWM_MspDeInitCallback = HAL_TIM_PWM_MspDeInit; /* Legacy weak PWM Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+ htim->OnePulse_MspInitCallback = HAL_TIM_OnePulse_MspInit; /* Legacy weak One Pulse Msp Init Callback */
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+ htim->OnePulse_MspDeInitCallback = HAL_TIM_OnePulse_MspDeInit; /* Legacy weak One Pulse Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+ htim->Encoder_MspInitCallback = HAL_TIM_Encoder_MspInit; /* Legacy weak Encoder Msp Init Callback */
+ break;
+
+ case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+ htim->Encoder_MspDeInitCallback = HAL_TIM_Encoder_MspDeInit; /* Legacy weak Encoder Msp DeInit Callback */
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+ htim->HallSensor_MspInitCallback = HAL_TIMEx_HallSensor_MspInit; /* Legacy weak Hall Sensor Msp Init Callback */
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+ htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit; /* Legacy weak Hall Sensor Msp DeInit Callback */
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(htim);
+
+ 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(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(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM PWM handle state.
+ * @param htim TIM handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM Input Capture handle state.
+ * @param htim TIM IC handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM One Pulse Mode handle state.
+ * @param htim TIM OPM handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM Encoder Mode handle state.
+ * @param htim TIM Encoder Interface handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @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;
+
+ 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 */
+}
+
+/**
+ * @brief TIM DMA Delay Pulse complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+ }
+ 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;
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+ }
+ 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;
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+ }
+ 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;
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+ }
+ 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;
+
+ 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;
+
+ htim->State = HAL_TIM_STATE_READY;
+
+#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;
+
+ 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;
+
+ htim->State = HAL_TIM_STATE_READY;
+
+#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, TIM_Base_InitTypeDef *Structure)
+{
+ uint32_t tmpcr1;
+ tmpcr1 = TIMx->CR1;
+
+ /* Set TIM Time Base Unit parameters ---------------------------------------*/
+ if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx))
+ {
+ /* Select the Counter Mode */
+ tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
+ tmpcr1 |= Structure->CounterMode;
+ }
+
+ if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
+ {
+ /* Set the clock division */
+ tmpcr1 &= ~TIM_CR1_CKD;
+ tmpcr1 |= (uint32_t)Structure->ClockDivision;
+ }
+
+ /* Set the auto-reload preload */
+ MODIFY_REG(tmpcr1, TIM_CR1_ARPE, Structure->AutoReloadPreload);
+
+ TIMx->CR1 = tmpcr1;
+
+ /* Set the Autoreload value */
+ TIMx->ARR = (uint32_t)Structure->Period ;
+
+ /* Set the Prescaler value */
+ TIMx->PSC = Structure->Prescaler;
+
+ if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))
+ {
+ /* Set the Repetition Counter value */
+ TIMx->RCR = Structure->RepetitionCounter;
+ }
+
+ /* Generate an update event to reload the Prescaler
+ and the repetition counter (only for advanced timer) value immediately */
+ TIMx->EGR = TIM_EGR_UG;
+}
+
+/**
+ * @brief Timer Output Compare 1 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The ouput configuration structure
+ * @retval None
+ */
+static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Disable the Channel 1: Reset the CC1E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC1E;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmrx = TIMx->CCMR1;
+
+ /* Reset the Output Compare Mode Bits */
+ tmpccmrx &= ~TIM_CCMR1_OC1M;
+ tmpccmrx &= ~TIM_CCMR1_CC1S;
+ /* Select the Output Compare Mode */
+ tmpccmrx |= OC_Config->OCMode;
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC1P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= OC_Config->OCPolarity;
+
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+ /* Reset the Output N Polarity level */
+ tmpccer &= ~TIM_CCER_CC1NP;
+ /* Set the Output N Polarity */
+ tmpccer |= OC_Config->OCNPolarity;
+ /* Reset the Output N State */
+ tmpccer &= ~TIM_CCER_CC1NE;
+ }
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* Reset the Output Compare and Output Compare N IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS1;
+ tmpcr2 &= ~TIM_CR2_OIS1N;
+ /* Set the Output Idle state */
+ tmpcr2 |= OC_Config->OCIdleState;
+ /* Set the Output N Idle state */
+ tmpcr2 |= OC_Config->OCNIdleState;
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR1 */
+ TIMx->CCMR1 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR1 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 2 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The ouput configuration structure
+ * @retval None
+ */
+void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Disable the Channel 2: Reset the CC2E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC2E;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmrx = TIMx->CCMR1;
+
+ /* Reset the Output Compare mode and Capture/Compare selection Bits */
+ tmpccmrx &= ~TIM_CCMR1_OC2M;
+ tmpccmrx &= ~TIM_CCMR1_CC2S;
+
+ /* Select the Output Compare Mode */
+ tmpccmrx |= (OC_Config->OCMode << 8U);
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC2P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 4U);
+
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_2))
+ {
+ assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+ /* Reset the Output N Polarity level */
+ tmpccer &= ~TIM_CCER_CC2NP;
+ /* Set the Output N Polarity */
+ tmpccer |= (OC_Config->OCNPolarity << 4U);
+ /* Reset the Output N State */
+ tmpccer &= ~TIM_CCER_CC2NE;
+
+ }
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* Reset the Output Compare and Output Compare N IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS2;
+ tmpcr2 &= ~TIM_CR2_OIS2N;
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 2U);
+ /* Set the Output N Idle state */
+ tmpcr2 |= (OC_Config->OCNIdleState << 2U);
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR1 */
+ TIMx->CCMR1 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR2 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 3 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The ouput configuration structure
+ * @retval None
+ */
+static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Disable the Channel 3: Reset the CC2E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC3E;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+
+ /* Get the TIMx CCMR2 register value */
+ tmpccmrx = TIMx->CCMR2;
+
+ /* Reset the Output Compare mode and Capture/Compare selection Bits */
+ tmpccmrx &= ~TIM_CCMR2_OC3M;
+ tmpccmrx &= ~TIM_CCMR2_CC3S;
+ /* Select the Output Compare Mode */
+ tmpccmrx |= OC_Config->OCMode;
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC3P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 8U);
+
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_3))
+ {
+ assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+ /* Reset the Output N Polarity level */
+ tmpccer &= ~TIM_CCER_CC3NP;
+ /* Set the Output N Polarity */
+ tmpccer |= (OC_Config->OCNPolarity << 8U);
+ /* Reset the Output N State */
+ tmpccer &= ~TIM_CCER_CC3NE;
+ }
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* Reset the Output Compare and Output Compare N IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS3;
+ tmpcr2 &= ~TIM_CR2_OIS3N;
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 4U);
+ /* Set the Output N Idle state */
+ tmpcr2 |= (OC_Config->OCNIdleState << 4U);
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR2 */
+ TIMx->CCMR2 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR3 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 4 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The ouput configuration structure
+ * @retval None
+ */
+static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Disable the Channel 4: Reset the CC4E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC4E;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+
+ /* Get the TIMx CCMR2 register value */
+ tmpccmrx = TIMx->CCMR2;
+
+ /* Reset the Output Compare mode and Capture/Compare selection Bits */
+ tmpccmrx &= ~TIM_CCMR2_OC4M;
+ tmpccmrx &= ~TIM_CCMR2_CC4S;
+
+ /* Select the Output Compare Mode */
+ tmpccmrx |= (OC_Config->OCMode << 8U);
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC4P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 12U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* Reset the Output Compare IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS4;
+
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 6U);
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR2 */
+ TIMx->CCMR2 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR4 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 5 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The ouput configuration structure
+ * @retval None
+ */
+static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx,
+ TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Disable the output: Reset the CCxE Bit */
+ TIMx->CCER &= ~TIM_CCER_CC5E;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+ /* Get the TIMx CCMR1 register value */
+ tmpccmrx = TIMx->CCMR3;
+
+ /* Reset the Output Compare Mode Bits */
+ tmpccmrx &= ~(TIM_CCMR3_OC5M);
+ /* Select the Output Compare Mode */
+ tmpccmrx |= OC_Config->OCMode;
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC5P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 16U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Reset the Output Compare IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS5;
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 8U);
+ }
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR3 */
+ TIMx->CCMR3 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR5 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 6 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The ouput configuration structure
+ * @retval None
+ */
+static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx,
+ TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Disable the output: Reset the CCxE Bit */
+ TIMx->CCER &= ~TIM_CCER_CC6E;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+ /* Get the TIMx CCMR1 register value */
+ tmpccmrx = TIMx->CCMR3;
+
+ /* Reset the Output Compare Mode Bits */
+ tmpccmrx &= ~(TIM_CCMR3_OC6M);
+ /* Select the Output Compare Mode */
+ tmpccmrx |= (OC_Config->OCMode << 8U);
+
+ /* Reset the Output Polarity level */
+ tmpccer &= (uint32_t)~TIM_CCER_CC6P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 20U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Reset the Output Compare IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS6;
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 10U);
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR3 */
+ TIMx->CCMR3 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR6 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Slave Timer configuration function
+ * @param htim TIM handle
+ * @param sSlaveConfig Slave timer configuration
+ * @retval None
+ */
+static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+ TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+ 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:
+ break;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the TI1 as Input.
+ * @param TIMx to select the TIM peripheral.
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICSELECTION_DIRECTTI: TIM Input 1 is selected to be connected to IC1.
+ * @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 1 is selected to be connected to IC2.
+ * @arg TIM_ICSELECTION_TRC: TIM Input 1 is selected to be connected to TRC.
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI2FP1
+ * (on channel2 path) is used as the input signal. Therefore CCMR1 must be
+ * protected against un-initialized filter and polarity values.
+ */
+void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Disable the Channel 1: Reset the CC1E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC1E;
+ tmpccmr1 = TIMx->CCMR1;
+ tmpccer = TIMx->CCER;
+
+ /* Select the Input */
+ if (IS_TIM_CC2_INSTANCE(TIMx) != RESET)
+ {
+ tmpccmr1 &= ~TIM_CCMR1_CC1S;
+ tmpccmr1 |= TIM_ICSelection;
+ }
+ else
+ {
+ tmpccmr1 |= TIM_CCMR1_CC1S_0;
+ }
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC1F;
+ tmpccmr1 |= ((TIM_ICFilter << 4U) & TIM_CCMR1_IC1F);
+
+ /* Select the Polarity and set the CC1E Bit */
+ tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+ tmpccer |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
+
+ /* Write to TIMx CCMR1 and CCER registers */
+ TIMx->CCMR1 = tmpccmr1;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the Polarity and Filter for TI1.
+ * @param TIMx to select the TIM peripheral.
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Disable the Channel 1: Reset the CC1E Bit */
+ tmpccer = TIMx->CCER;
+ TIMx->CCER &= ~TIM_CCER_CC1E;
+ tmpccmr1 = TIMx->CCMR1;
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC1F;
+ tmpccmr1 |= (TIM_ICFilter << 4U);
+
+ /* Select the Polarity and set the CC1E Bit */
+ tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+ tmpccer |= TIM_ICPolarity;
+
+ /* Write to TIMx CCMR1 and CCER registers */
+ TIMx->CCMR1 = tmpccmr1;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the TI2 as Input.
+ * @param TIMx to select the TIM peripheral
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICSELECTION_DIRECTTI: TIM Input 2 is selected to be connected to IC2.
+ * @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 2 is selected to be connected to IC1.
+ * @arg TIM_ICSELECTION_TRC: TIM Input 2 is selected to be connected to TRC.
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI1FP2
+ * (on channel1 path) is used as the input signal. Therefore CCMR1 must be
+ * protected against un-initialized filter and polarity values.
+ */
+static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Disable the Channel 2: Reset the CC2E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC2E;
+ tmpccmr1 = TIMx->CCMR1;
+ tmpccer = TIMx->CCER;
+
+ /* Select the Input */
+ tmpccmr1 &= ~TIM_CCMR1_CC2S;
+ tmpccmr1 |= (TIM_ICSelection << 8U);
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC2F;
+ tmpccmr1 |= ((TIM_ICFilter << 12U) & TIM_CCMR1_IC2F);
+
+ /* Select the Polarity and set the CC2E Bit */
+ tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ tmpccer |= ((TIM_ICPolarity << 4U) & (TIM_CCER_CC2P | TIM_CCER_CC2NP));
+
+ /* Write to TIMx CCMR1 and CCER registers */
+ TIMx->CCMR1 = tmpccmr1 ;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the Polarity and Filter for TI2.
+ * @param TIMx to select the TIM peripheral.
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Disable the Channel 2: Reset the CC2E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC2E;
+ tmpccmr1 = TIMx->CCMR1;
+ tmpccer = TIMx->CCER;
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC2F;
+ tmpccmr1 |= (TIM_ICFilter << 12U);
+
+ /* Select the Polarity and set the CC2E Bit */
+ tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ tmpccer |= (TIM_ICPolarity << 4U);
+
+ /* Write to TIMx CCMR1 and CCER registers */
+ TIMx->CCMR1 = tmpccmr1 ;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the TI3 as Input.
+ * @param TIMx to select the TIM peripheral
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICSELECTION_DIRECTTI: TIM Input 3 is selected to be connected to IC3.
+ * @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 3 is selected to be connected to IC4.
+ * @arg TIM_ICSELECTION_TRC: TIM Input 3 is selected to be connected to TRC.
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI3FP4
+ * (on channel1 path) is used as the input signal. Therefore CCMR2 must be
+ * protected against un-initialized filter and polarity values.
+ */
+static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr2;
+ uint32_t tmpccer;
+
+ /* Disable the Channel 3: Reset the CC3E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC3E;
+ tmpccmr2 = TIMx->CCMR2;
+ tmpccer = TIMx->CCER;
+
+ /* Select the Input */
+ tmpccmr2 &= ~TIM_CCMR2_CC3S;
+ tmpccmr2 |= TIM_ICSelection;
+
+ /* Set the filter */
+ tmpccmr2 &= ~TIM_CCMR2_IC3F;
+ tmpccmr2 |= ((TIM_ICFilter << 4U) & TIM_CCMR2_IC3F);
+
+ /* Select the Polarity and set the CC3E Bit */
+ tmpccer &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP);
+ tmpccer |= ((TIM_ICPolarity << 8U) & (TIM_CCER_CC3P | TIM_CCER_CC3NP));
+
+ /* Write to TIMx CCMR2 and CCER registers */
+ TIMx->CCMR2 = tmpccmr2;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the TI4 as Input.
+ * @param TIMx to select the TIM peripheral
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICSELECTION_DIRECTTI: TIM Input 4 is selected to be connected to IC4.
+ * @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 4 is selected to be connected to IC3.
+ * @arg TIM_ICSELECTION_TRC: TIM Input 4 is selected to be connected to TRC.
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI4FP3
+ * (on channel1 path) is used as the input signal. Therefore CCMR2 must be
+ * protected against un-initialized filter and polarity values.
+ * @retval None
+ */
+static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr2;
+ uint32_t tmpccer;
+
+ /* Disable the Channel 4: Reset the CC4E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC4E;
+ tmpccmr2 = TIMx->CCMR2;
+ tmpccer = TIMx->CCER;
+
+ /* Select the Input */
+ tmpccmr2 &= ~TIM_CCMR2_CC4S;
+ tmpccmr2 |= (TIM_ICSelection << 8U);
+
+ /* Set the filter */
+ tmpccmr2 &= ~TIM_CCMR2_IC4F;
+ tmpccmr2 |= ((TIM_ICFilter << 12U) & TIM_CCMR2_IC4F);
+
+ /* Select the Polarity and set the CC4E Bit */
+ tmpccer &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP);
+ tmpccer |= ((TIM_ICPolarity << 12U) & (TIM_CCER_CC4P | TIM_CCER_CC4NP));
+
+ /* Write to TIMx CCMR2 and CCER registers */
+ TIMx->CCMR2 = tmpccmr2;
+ TIMx->CCER = tmpccer ;
+}
+
+/**
+ * @brief Selects the Input Trigger source
+ * @param TIMx to select the TIM peripheral
+ * @param InputTriggerSource The Input Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM_TS_ITR0: Internal Trigger 0
+ * @arg TIM_TS_ITR1: Internal Trigger 1
+ * @arg TIM_TS_ITR2: Internal Trigger 2
+ * @arg TIM_TS_ITR3: Internal Trigger 3
+ * @arg TIM_TS_TI1F_ED: TI1 Edge Detector
+ * @arg TIM_TS_TI1FP1: Filtered Timer Input 1
+ * @arg TIM_TS_TI2FP2: Filtered Timer Input 2
+ * @arg TIM_TS_ETRF: External Trigger input
+ * @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 (*)
+ *
+ * (*) 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
+ * @arg TIM_CHANNEL_2: TIM Channel 2
+ * @arg TIM_CHANNEL_3: TIM Channel 3
+ * @arg TIM_CHANNEL_4: TIM Channel 4
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @param ChannelState specifies the TIM Channel CCxE bit new state.
+ * This parameter can be: TIM_CCx_ENABLE or TIM_CCx_DISABLE.
+ * @retval None
+ */
+void TIM_CCxChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(TIMx));
+ assert_param(IS_TIM_CHANNELS(Channel));
+
+ tmp = TIM_CCER_CC1E << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */
+
+ /* Reset the CCxE Bit */
+ TIMx->CCER &= ~tmp;
+
+ /* Set or reset the CCxE Bit */
+ TIMx->CCER |= (uint32_t)(ChannelState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
+}
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Reset interrupt callbacks to the legacy weak callbacks.
+ * @param htim pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+void TIM_ResetCallback(TIM_HandleTypeDef *htim)
+{
+ /* Reset the TIM callback to the legacy weak callbacks */
+ htim->PeriodElapsedCallback = HAL_TIM_PeriodElapsedCallback; /* Legacy weak PeriodElapsedCallback */
+ htim->PeriodElapsedHalfCpltCallback = HAL_TIM_PeriodElapsedHalfCpltCallback; /* Legacy weak PeriodElapsedHalfCpltCallback */
+ htim->TriggerCallback = HAL_TIM_TriggerCallback; /* Legacy weak TriggerCallback */
+ htim->TriggerHalfCpltCallback = HAL_TIM_TriggerHalfCpltCallback; /* Legacy weak TriggerHalfCpltCallback */
+ htim->IC_CaptureCallback = HAL_TIM_IC_CaptureCallback; /* Legacy weak IC_CaptureCallback */
+ htim->IC_CaptureHalfCpltCallback = HAL_TIM_IC_CaptureHalfCpltCallback; /* Legacy weak IC_CaptureHalfCpltCallback */
+ htim->OC_DelayElapsedCallback = HAL_TIM_OC_DelayElapsedCallback; /* Legacy weak OC_DelayElapsedCallback */
+ htim->PWM_PulseFinishedCallback = HAL_TIM_PWM_PulseFinishedCallback; /* Legacy weak PWM_PulseFinishedCallback */
+ htim->PWM_PulseFinishedHalfCpltCallback = HAL_TIM_PWM_PulseFinishedHalfCpltCallback; /* Legacy weak PWM_PulseFinishedHalfCpltCallback */
+ htim->ErrorCallback = HAL_TIM_ErrorCallback; /* Legacy weak ErrorCallback */
+ htim->CommutationCallback = HAL_TIMEx_CommutCallback; /* Legacy weak CommutationCallback */
+ htim->CommutationHalfCpltCallback = HAL_TIMEx_CommutHalfCpltCallback; /* Legacy weak CommutationHalfCpltCallback */
+ htim->BreakCallback = HAL_TIMEx_BreakCallback; /* Legacy weak BreakCallback */
+ htim->Break2Callback = HAL_TIMEx_Break2Callback; /* Legacy weak Break2Callback */
+}
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_tim_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_tim_ex.c
new file mode 100644
index 0000000000..1dcd77049c
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_tim_ex.c
@@ -0,0 +1,2324 @@
+/**
+ ******************************************************************************
+ * @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
+ @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_OC_Start_IT()
+ (++) Complementary PWM generation : HAL_TIMEx_PWMN_Start(), HAL_TIMEx_PWMN_Start_DMA(), HAL_TIMEx_PWMN_Start_IT()
+ (++) Complementary One-pulse mode output : HAL_TIMEx_OnePulseN_Start(), HAL_TIMEx_OnePulseN_Start_IT()
+ (++) Hall Sensor output : HAL_TIMEx_HallSensor_Start(), HAL_TIMEx_HallSensor_Start_DMA(), HAL_TIMEx_HallSensor_Start_IT().
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+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.
+ * @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, 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_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 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 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;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+ /* 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 */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __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);
+
+ /* 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;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+ /* 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 */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __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);
+
+ /* 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;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+ if (htim->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if (((uint32_t)pData == 0U) && (Length > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ /* 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 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 */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __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);
+
+ /* 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));
+
+ /* 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 */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __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);
+
+ /* 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)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Output Compare interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Output Compare interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Output Compare interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+
+ default:
+ break;
+ }
+
+ /* Enable the TIM Break interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
+
+ /* Enable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation in interrupt mode
+ * on the complementary output.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ 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:
+ break;
+ }
+
+ /* Disable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the TIM Break interrupt (only if no more channel is active) */
+ tmpccer = htim->Instance->CCER;
+ if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == (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);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Output Compare signal generation in DMA mode
+ * on the complementary output.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @param pData The source Buffer address.
+ * @param Length The length of data to be transferred from memory to TIM peripheral
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ if (htim->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if (((uint32_t)pData == 0U) && (Length > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+ 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 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_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 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_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 HAL_ERROR;
+ }
+ /* Enable the TIM Output Compare DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Enable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation in DMA mode
+ * on the complementary output.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Output Compare DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (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:
+ break;
+ }
+
+ /* Disable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions
+ * @brief Timer Complementary PWM functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Timer Complementary PWM functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Start the Complementary PWM.
+ (+) Stop the Complementary PWM.
+ (+) Start the Complementary PWM and enable interrupts.
+ (+) Stop the Complementary PWM and disable interrupts.
+ (+) Start the Complementary PWM and enable DMA transfers.
+ (+) Stop the Complementary PWM and disable DMA transfers.
+ (+) Start the Complementary Input Capture measurement.
+ (+) Stop the Complementary Input Capture.
+ (+) Start the Complementary Input Capture and enable interrupts.
+ (+) Stop the Complementary Input Capture and disable interrupts.
+ (+) Start the Complementary Input Capture and enable DMA transfers.
+ (+) Stop the Complementary Input Capture and disable DMA transfers.
+ (+) Start the Complementary One Pulse generation.
+ (+) Stop the Complementary One Pulse.
+ (+) Start the Complementary One Pulse and enable interrupts.
+ (+) Stop the Complementary One Pulse and disable interrupts.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Starts the PWM signal generation on the complementary output.
+ * @param htim 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));
+
+ /* 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 */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __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);
+
+ /* 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)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Enable the TIM Break interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
+
+ /* Enable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the PWM signal generation in interrupt mode on the
+ * complementary output.
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ 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:
+ break;
+ }
+
+ /* Disable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the TIM Break interrupt (only if no more channel is active) */
+ tmpccer = htim->Instance->CCER;
+ if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == (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);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM PWM signal generation in DMA mode on the
+ * complementary output
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @param pData The source Buffer address.
+ * @param Length The length of data to be transferred from memory to TIM peripheral
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ if (htim->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if (((uint32_t)pData == 0U) && (Length > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ 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 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 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 HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Enable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM PWM signal generation in DMA mode on the complementary
+ * output
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (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:
+ break;
+ }
+
+ /* Disable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions
+ * @brief Timer Complementary One Pulse functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Timer Complementary One Pulse functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Start the Complementary One Pulse generation.
+ (+) Stop the Complementary One Pulse.
+ (+) Start the Complementary One Pulse and enable interrupts.
+ (+) Stop the Complementary One Pulse and disable interrupts.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Starts the TIM One Pulse signal generation on the complementary
+ * output.
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Enable the complementary One Pulse output */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM One Pulse signal generation on the complementary
+ * output.
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Disable the complementary One Pulse output */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM One Pulse signal generation in interrupt mode on the
+ * complementary channel.
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+
+ /* Enable the complementary One Pulse output */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM One Pulse signal generation in interrupt mode on the
+ * complementary channel.
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+
+ /* Disable the complementary One Pulse output */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Configure the 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
+ * @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_ITR2: Internal trigger 12 selected (*)
+ * @arg TIM_TS_ITR3: Internal trigger 13 selected (*)
+ * @arg TIM_TS_NONE: No trigger is needed
+ * @param CommutationSource the Commutation Event source
+ * This parameter can be one of the following values:
+ * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+ * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_IT(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
+ uint32_t CommutationSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+ __HAL_LOCK(htim);
+
+ if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+ (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3) ||
+ (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_ITR2: Internal trigger 12 selected (*)
+ * @arg TIM_TS_ITR3: 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,
+ 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,
+ TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig)
+{
+ /* Keep this variable initialized to 0 as it is used to configure BDTR register */
+ uint32_t tmpbdtr = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_OSSR_STATE(sBreakDeadTimeConfig->OffStateRunMode));
+ assert_param(IS_TIM_OSSI_STATE(sBreakDeadTimeConfig->OffStateIDLEMode));
+ assert_param(IS_TIM_LOCK_LEVEL(sBreakDeadTimeConfig->LockLevel));
+ assert_param(IS_TIM_DEADTIME(sBreakDeadTimeConfig->DeadTime));
+ assert_param(IS_TIM_BREAK_STATE(sBreakDeadTimeConfig->BreakState));
+ assert_param(IS_TIM_BREAK_POLARITY(sBreakDeadTimeConfig->BreakPolarity));
+ assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->BreakFilter));
+ assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(sBreakDeadTimeConfig->AutomaticOutput));
+
+ /* Check input state */
+ __HAL_LOCK(htim);
+
+ /* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State,
+ the OSSI State, the dead time value and the Automatic Output Enable Bit */
+
+ /* Set the BDTR bits */
+ MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, sBreakDeadTimeConfig->DeadTime);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, sBreakDeadTimeConfig->LockLevel);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, sBreakDeadTimeConfig->OffStateIDLEMode);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, sBreakDeadTimeConfig->OffStateRunMode);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, sBreakDeadTimeConfig->BreakState);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, sBreakDeadTimeConfig->BreakPolarity);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, sBreakDeadTimeConfig->AutomaticOutput);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, (sBreakDeadTimeConfig->BreakFilter << TIM_BDTR_BKF_Pos));
+
+ if (IS_TIM_BKIN2_INSTANCE(htim->Instance))
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_BREAK2_STATE(sBreakDeadTimeConfig->Break2State));
+ assert_param(IS_TIM_BREAK2_POLARITY(sBreakDeadTimeConfig->Break2Polarity));
+ assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->Break2Filter));
+
+ /* Set the BREAK2 input related BDTR bits */
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (sBreakDeadTimeConfig->Break2Filter << TIM_BDTR_BK2F_Pos));
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, sBreakDeadTimeConfig->Break2State);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, sBreakDeadTimeConfig->Break2Polarity);
+ }
+
+ /* 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,
+ TIMEx_BreakInputConfigTypeDef *sBreakInputConfig)
+
+{
+ 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 = 8U;
+ 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:
+ break;
+ }
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+#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: TIM15 TI1 is connected to TIM2 CH1
+ * @arg TIM_TIM15_TI1_TIM3: TIM15 TI1 is connected to TIM3 CH1
+ * @arg TIM_TIM15_TI1_TIM4: TIM15 TI1 is connected to TIM4 CH1
+ * @arg TIM_TIM15_TI1_LSE: TIM15 TI1 is connected to LSE
+ * @arg TIM_TIM15_TI1_CSI: TIM15 TI1 is connected to CSI
+ * @arg TIM_TIM15_TI1_MCO2: TIM15 TI1 is connected to MCO2
+ * @arg TIM_TIM15_TI2_GPIO: TIM15 TI2 is connected to GPIO
+ * @arg TIM_TIM15_TI2_TIM2: TIM15 TI2 is connected to TIM2 CH2
+ * @arg TIM_TIM15_TI2_TIM3: TIM15 TI2 is connected to TIM3 CH2
+ * @arg TIM_TIM15_TI2_TIM4: 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_LSI: TIM16 TI1 is connected to LSI
+ * @arg TIM_TIM16_TI1_LSE: TIM16 TI1 is connected to LSE
+ * @arg TIM_TIM16_TI1_RTC: TIM16 TI1 is connected to RTC wakeup interrupt
+ *
+ * For TIM17, the parameter can have the following values:
+ * @arg TIM_TIM17_TI1_GPIO: TIM17 TI1 is connected to GPIO
+ * @arg TIM_TIM17_TI1_SPDIF_FS: TIM17 TI1 is connected to SPDIF FS (*)
+ * @arg TIM_TIM17_TI1_HSE_1MHZ: TIM17 TI1 is connected to HSE 1MHz
+ * @arg TIM_TIM17_TI1_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;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions
+ * @brief Extended Callbacks functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Extended Callbacks functions #####
+ ==============================================================================
+ [..]
+ This section provides Extended TIM callback functions:
+ (+) Timer Commutation callback
+ (+) Timer Break callback
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Hall commutation changed callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_CommutCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIMEx_CommutCallback could be implemented in the user file
+ */
+}
+/**
+ * @brief Hall commutation changed half complete callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_CommutHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIMEx_CommutHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Hall Break detection callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIMEx_BreakCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Hall Break2 detection callback in non blocking mode
+ * @param htim: TIM handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_Break2Callback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_TIMEx_Break2Callback could be implemented in the user file
+ */
+}
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions
+ * @brief Extended Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Extended Peripheral State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the TIM Hall Sensor interface handle state.
+ * @param htim TIM Hall Sensor handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup TIMEx_Private_Functions TIMEx 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 Enables or disables the TIM Capture Compare Channel xN.
+ * @param TIMx to select the TIM peripheral
+ * @param Channel specifies the TIM Channel
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1
+ * @arg TIM_CHANNEL_2: TIM Channel 2
+ * @arg TIM_CHANNEL_3: TIM Channel 3
+ * @param ChannelNState specifies the TIM Channel CCxNE bit new state.
+ * This parameter can be: TIM_CCxN_ENABLE or TIM_CCxN_Disable.
+ * @retval None
+ */
+static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState)
+{
+ uint32_t tmp;
+
+ tmp = TIM_CCER_CC1NE << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */
+
+ /* Reset the CCxNE Bit */
+ TIMx->CCER &= ~tmp;
+
+ /* Set or reset the CCxNE Bit */
+ TIMx->CCER |= (uint32_t)(ChannelNState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
+}
+/**
+ * @}
+ */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart.c
new file mode 100644
index 0000000000..85a0b6e8e9
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart.c
@@ -0,0 +1,4115 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_uart.c
+ * @author MCD Application Team
+ * @brief UART HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART).
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ *
+ *
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The UART HAL driver can be used as follows:
+
+ (#) Declare a UART_HandleTypeDef handle structure (eg. UART_HandleTypeDef huart).
+ (#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API:
+ (++) Enable the USARTx interface clock.
+ (++) UART pins configuration:
+ (+++) Enable the clock for the UART GPIOs.
+ (+++) Configure these UART pins as alternate function pull-up.
+ (++) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT()
+ and HAL_UART_Receive_IT() APIs):
+ (+++) Configure the USARTx interrupt priority.
+ (+++) Enable the NVIC USART IRQ handle.
+ (++) UART interrupts handling:
+ -@@- The specific UART interrupts (Transmission complete interrupt,
+ RXNE interrupt, RX/TX FIFOs related interrupts and Error Interrupts)
+ are managed using the macros __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT()
+ inside the transmit and receive processes.
+ (++) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA()
+ and HAL_UART_Receive_DMA() APIs):
+ (+++) Declare a DMA handle structure for the Tx/Rx channel.
+ (+++) Enable the DMAx interface clock.
+ (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
+ (+++) Configure the DMA Tx/Rx channel.
+ (+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
+
+ (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Prescaler value , Hardware
+ flow control and Mode (Receiver/Transmitter) in the huart handle Init structure.
+
+ (#) If required, program UART advanced features (TX/RX pins swap, auto Baud rate detection,...)
+ in the huart handle AdvancedInit structure.
+
+ (#) For the UART asynchronous mode, initialize the UART registers by calling
+ the HAL_UART_Init() API.
+
+ (#) For the UART Half duplex mode, initialize the UART registers by calling
+ the HAL_HalfDuplex_Init() API.
+
+ (#) For the UART LIN (Local Interconnection Network) mode, initialize the UART registers
+ by calling the HAL_LIN_Init() API.
+
+ (#) For the UART Multiprocessor mode, initialize the UART registers
+ by calling the HAL_MultiProcessor_Init() API.
+
+ (#) For the UART RS485 Driver Enabled mode, initialize the UART registers
+ by calling the HAL_RS485Ex_Init() API.
+
+ [..]
+ (@) These API's (HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init(), HAL_MultiProcessor_Init(),
+ also configure the low level Hardware GPIO, CLOCK, CORTEX...etc) by
+ calling the customized HAL_UART_MspInit() API.
+
+ ##### Callback registration #####
+ ==================================
+
+ [..]
+ The compilation define USE_HAL_UART_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ [..]
+ Use Function @ref HAL_UART_RegisterCallback() to register a user callback.
+ Function @ref HAL_UART_RegisterCallback() allows to register following callbacks:
+ (+) TxHalfCpltCallback : Tx Half Complete Callback.
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxHalfCpltCallback : Rx Half Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) AbortCpltCallback : Abort Complete Callback.
+ (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
+ (+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
+ (+) WakeupCallback : Wakeup Callback.
+ (+) RxFifoFullCallback : Rx Fifo Full Callback.
+ (+) TxFifoEmptyCallback : Tx Fifo Empty Callback.
+ (+) MspInitCallback : UART MspInit.
+ (+) MspDeInitCallback : UART MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function @ref HAL_UART_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function.
+ @ref HAL_UART_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxHalfCpltCallback : Tx Half Complete Callback.
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxHalfCpltCallback : Rx Half Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) AbortCpltCallback : Abort Complete Callback.
+ (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
+ (+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
+ (+) WakeupCallback : Wakeup Callback.
+ (+) RxFifoFullCallback : Rx Fifo Full Callback.
+ (+) TxFifoEmptyCallback : Tx Fifo Empty Callback.
+ (+) MspInitCallback : UART MspInit.
+ (+) MspDeInitCallback : UART MspDeInit.
+
+ [..]
+ By default, after the @ref HAL_UART_Init() and when the state is HAL_UART_STATE_RESET
+ all callbacks are set to the corresponding weak (surcharged) functions:
+ examples @ref HAL_UART_TxCpltCallback(), @ref HAL_UART_RxHalfCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_UART_Init()
+ and @ref HAL_UART_DeInit() only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_UART_Init() and @ref HAL_UART_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
+
+ [..]
+ Callbacks can be registered/unregistered in HAL_UART_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_UART_STATE_READY or HAL_UART_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 @ref HAL_UART_RegisterCallback() before calling @ref HAL_UART_DeInit()
+ or @ref HAL_UART_Init() function.
+
+ [..]
+ When The compilation define USE_HAL_UART_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available
+ and weak (surcharged) callbacks are used.
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup UART UART
+ * @brief HAL UART module driver
+ * @{
+ */
+
+#ifdef HAL_UART_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup UART_Private_Constants UART Private Constants
+ * @{
+ */
+#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \
+ USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8| \
+ USART_CR1_FIFOEN )) /*!< UART or USART CR1 fields of parameters set by UART_SetConfig API */
+
+#define USART_CR3_FIELDS ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_ONEBIT| \
+ USART_CR3_TXFTCFG | USART_CR3_RXFTCFG )) /*!< UART or USART CR3 fields of parameters set by UART_SetConfig API */
+
+#define LPUART_BRR_MIN 0x00000300U /* LPUART BRR minimum authorized value */
+#define LPUART_BRR_MAX 0x000FFFFFU /* LPUART BRR maximum authorized value */
+
+#define UART_BRR_MIN 0x10U /* UART BRR minimum authorized value */
+#define UART_BRR_MAX 0x0000FFFFU /* UART BRR maximum authorized value */
+
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup UART_Private_Functions
+ * @{
+ */
+static void UART_EndTxTransfer(UART_HandleTypeDef *huart);
+static void UART_EndRxTransfer(UART_HandleTypeDef *huart);
+static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
+static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
+static void UART_DMAError(DMA_HandleTypeDef *hdma);
+static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma);
+static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
+static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
+static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
+static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
+static void UART_TxISR_8BIT(UART_HandleTypeDef *huart);
+static void UART_TxISR_16BIT(UART_HandleTypeDef *huart);
+static void UART_TxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart);
+static void UART_TxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart);
+static void UART_EndTransmit_IT(UART_HandleTypeDef *huart);
+static void UART_RxISR_8BIT(UART_HandleTypeDef *huart);
+static void UART_RxISR_16BIT(UART_HandleTypeDef *huart);
+static void UART_RxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart);
+static void UART_RxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup UART_Exported_Functions UART Exported Functions
+ * @{
+ */
+
+/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
+ in asynchronous mode.
+ (+) For the asynchronous mode the parameters below can be configured:
+ (++) Baud Rate
+ (++) Word Length
+ (++) Stop Bit
+ (++) Parity: If the parity is enabled, then the MSB bit of the data written
+ in the data register is transmitted but is changed by the parity bit.
+ (++) Hardware flow control
+ (++) Receiver/transmitter modes
+ (++) Over Sampling Method
+ (++) One-Bit Sampling Method
+ (+) For the asynchronous mode, the following advanced features can be configured as well:
+ (++) TX and/or RX pin level inversion
+ (++) data logical level inversion
+ (++) RX and TX pins swap
+ (++) RX overrun detection disabling
+ (++) DMA disabling on RX error
+ (++) MSB first on communication line
+ (++) auto Baud rate detection
+ [..]
+ The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init()and HAL_MultiProcessor_Init()API
+ follow respectively the UART asynchronous, UART Half duplex, UART LIN mode
+ and UART multiprocessor mode configuration procedures (details for the procedures
+ are available in reference manual).
+
+@endverbatim
+
+ Depending on the frame length defined by the M1 and M0 bits (7-bit,
+ 8-bit or 9-bit), the possible UART formats are listed in the
+ following table.
+
+ Table 1. UART frame format.
+ +-----------------------------------------------------------------------+
+ | M1 bit | M0 bit | PCE bit | UART frame |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 0 | | SB | 8 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 0 | | SB | 9 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 0 | | SB | 7 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | |
+ +-----------------------------------------------------------------------+
+
+ * @{
+ */
+
+/**
+ * @brief Initialize the UART mode according to the specified
+ * parameters in the UART_InitTypeDef and initialize the associated handle.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
+{
+ /* Check the UART handle allocation */
+ if (huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->Init.HwFlowCtl != UART_HWCONTROL_NONE)
+ {
+ /* Check the parameters */
+ assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance));
+ }
+ else
+ {
+ /* Check the parameters */
+ assert_param((IS_UART_INSTANCE(huart->Instance)) || (IS_LPUART_INSTANCE(huart->Instance)));
+ }
+
+ if (huart->gState == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ UART_InitCallbacksToDefault(huart);
+
+ if (huart->MspInitCallback == NULL)
+ {
+ huart->MspInitCallback = HAL_UART_MspInit;
+ }
+
+ /* Init the low level hardware */
+ huart->MspInitCallback(huart);
+#else
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_UART_MspInit(huart);
+#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
+ }
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* In asynchronous mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bits in the USART_CR2 register,
+ - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/
+ CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
+
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+/**
+ * @brief Initialize the half-duplex mode according to the specified
+ * parameters in the UART_InitTypeDef and creates the associated handle.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart)
+{
+ /* Check the UART handle allocation */
+ if (huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check UART instance */
+ assert_param(IS_UART_HALFDUPLEX_INSTANCE(huart->Instance));
+
+ if (huart->gState == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ UART_InitCallbacksToDefault(huart);
+
+ if (huart->MspInitCallback == NULL)
+ {
+ huart->MspInitCallback = HAL_UART_MspInit;
+ }
+
+ /* Init the low level hardware */
+ huart->MspInitCallback(huart);
+#else
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_UART_MspInit(huart);
+#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
+ }
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* In half-duplex mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bits in the USART_CR2 register,
+ - SCEN and IREN bits in the USART_CR3 register.*/
+ CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_IREN | USART_CR3_SCEN));
+
+ /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */
+ SET_BIT(huart->Instance->CR3, USART_CR3_HDSEL);
+
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+
+/**
+ * @brief Initialize the LIN mode according to the specified
+ * parameters in the UART_InitTypeDef and creates the associated handle.
+ * @param huart UART handle.
+ * @param BreakDetectLength Specifies the LIN break detection length.
+ * This parameter can be one of the following values:
+ * @arg @ref UART_LINBREAKDETECTLENGTH_10B 10-bit break detection
+ * @arg @ref UART_LINBREAKDETECTLENGTH_11B 11-bit break detection
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength)
+{
+ /* Check the UART handle allocation */
+ if (huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the LIN UART instance */
+ assert_param(IS_UART_LIN_INSTANCE(huart->Instance));
+ /* Check the Break detection length parameter */
+ assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength));
+
+ /* LIN mode limited to 16-bit oversampling only */
+ if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
+ {
+ return HAL_ERROR;
+ }
+ /* LIN mode limited to 8-bit data length */
+ if (huart->Init.WordLength != UART_WORDLENGTH_8B)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->gState == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ UART_InitCallbacksToDefault(huart);
+
+ if (huart->MspInitCallback == NULL)
+ {
+ huart->MspInitCallback = HAL_UART_MspInit;
+ }
+
+ /* Init the low level hardware */
+ huart->MspInitCallback(huart);
+#else
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_UART_MspInit(huart);
+#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
+ }
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* In LIN mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bits in the USART_CR2 register,
+ - SCEN and IREN bits in the USART_CR3 register.*/
+ CLEAR_BIT(huart->Instance->CR2, USART_CR2_CLKEN);
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_HDSEL | USART_CR3_IREN | USART_CR3_SCEN));
+
+ /* Enable the LIN mode by setting the LINEN bit in the CR2 register */
+ SET_BIT(huart->Instance->CR2, USART_CR2_LINEN);
+
+ /* Set the USART LIN Break detection length. */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_LBDL, BreakDetectLength);
+
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+
+/**
+ * @brief Initialize the multiprocessor mode according to the specified
+ * parameters in the UART_InitTypeDef and initialize the associated handle.
+ * @param huart UART handle.
+ * @param Address UART node address (4-, 6-, 7- or 8-bit long).
+ * @param WakeUpMethod Specifies the UART wakeup method.
+ * This parameter can be one of the following values:
+ * @arg @ref UART_WAKEUPMETHOD_IDLELINE WakeUp by an idle line detection
+ * @arg @ref UART_WAKEUPMETHOD_ADDRESSMARK WakeUp by an address mark
+ * @note If the user resorts to idle line detection wake up, the Address parameter
+ * is useless and ignored by the initialization function.
+ * @note If the user resorts to address mark wake up, the address length detection
+ * is configured by default to 4 bits only. For the UART to be able to
+ * manage 6-, 7- or 8-bit long addresses detection, the API
+ * HAL_MultiProcessorEx_AddressLength_Set() must be called after
+ * HAL_MultiProcessor_Init().
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod)
+{
+ /* Check the UART handle allocation */
+ if (huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the wake up method parameter */
+ assert_param(IS_UART_WAKEUPMETHOD(WakeUpMethod));
+
+ if (huart->gState == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ UART_InitCallbacksToDefault(huart);
+
+ if (huart->MspInitCallback == NULL)
+ {
+ huart->MspInitCallback = HAL_UART_MspInit;
+ }
+
+ /* Init the low level hardware */
+ huart->MspInitCallback(huart);
+#else
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_UART_MspInit(huart);
+#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
+ }
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* In multiprocessor mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bits in the USART_CR2 register,
+ - SCEN, HDSEL and IREN bits in the USART_CR3 register. */
+ CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
+
+ if (WakeUpMethod == UART_WAKEUPMETHOD_ADDRESSMARK)
+ {
+ /* If address mark wake up method is chosen, set the USART address node */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)Address << UART_CR2_ADDRESS_LSB_POS));
+ }
+
+ /* Set the wake up method by setting the WAKE bit in the CR1 register */
+ MODIFY_REG(huart->Instance->CR1, USART_CR1_WAKE, WakeUpMethod);
+
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+
+/**
+ * @brief DeInitialize the UART peripheral.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart)
+{
+ /* Check the UART handle allocation */
+ if (huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param((IS_UART_INSTANCE(huart->Instance)) || (IS_LPUART_INSTANCE(huart->Instance)));
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ __HAL_UART_DISABLE(huart);
+
+ huart->Instance->CR1 = 0x0U;
+ huart->Instance->CR2 = 0x0U;
+ huart->Instance->CR3 = 0x0U;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ if (huart->MspDeInitCallback == NULL)
+ {
+ huart->MspDeInitCallback = HAL_UART_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ huart->MspDeInitCallback(huart);
+#else
+ /* DeInit the low level hardware */
+ HAL_UART_MspDeInit(huart);
+#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->gState = HAL_UART_STATE_RESET;
+ huart->RxState = HAL_UART_STATE_RESET;
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the UART MSP.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the UART MSP.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_MspDeInit can be implemented in the user file
+ */
+}
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User UART Callback
+ * To be used instead of the weak predefined callback
+ * @param huart uart handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_UART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
+ * @arg @ref HAL_UART_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_UART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
+ * @arg @ref HAL_UART_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_UART_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_UART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
+ * @arg @ref HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
+ * @arg @ref HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
+ * @arg @ref HAL_UART_WAKEUP_CB_ID Wakeup Callback ID
+ * @arg @ref HAL_UART_RX_FIFO_FULL_CB_ID Rx Fifo Full Callback ID
+ * @arg @ref HAL_UART_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty Callback ID
+ * @arg @ref HAL_UART_MSPINIT_CB_ID MspInit Callback ID
+ * @arg @ref HAL_UART_MSPDEINIT_CB_ID MspDeInit Callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_RegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID,
+ pUART_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ __HAL_LOCK(huart);
+
+ if (huart->gState == HAL_UART_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_UART_TX_HALFCOMPLETE_CB_ID :
+ huart->TxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_UART_TX_COMPLETE_CB_ID :
+ huart->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_UART_RX_HALFCOMPLETE_CB_ID :
+ huart->RxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_UART_RX_COMPLETE_CB_ID :
+ huart->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_UART_ERROR_CB_ID :
+ huart->ErrorCallback = pCallback;
+ break;
+
+ case HAL_UART_ABORT_COMPLETE_CB_ID :
+ huart->AbortCpltCallback = pCallback;
+ break;
+
+ case HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID :
+ huart->AbortTransmitCpltCallback = pCallback;
+ break;
+
+ case HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID :
+ huart->AbortReceiveCpltCallback = pCallback;
+ break;
+
+ case HAL_UART_WAKEUP_CB_ID :
+ huart->WakeupCallback = pCallback;
+ break;
+
+ case HAL_UART_RX_FIFO_FULL_CB_ID :
+ huart->RxFifoFullCallback = pCallback;
+ break;
+
+ case HAL_UART_TX_FIFO_EMPTY_CB_ID :
+ huart->TxFifoEmptyCallback = pCallback;
+ break;
+
+ case HAL_UART_MSPINIT_CB_ID :
+ huart->MspInitCallback = pCallback;
+ break;
+
+ case HAL_UART_MSPDEINIT_CB_ID :
+ huart->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
+
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (huart->gState == HAL_UART_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_UART_MSPINIT_CB_ID :
+ huart->MspInitCallback = pCallback;
+ break;
+
+ case HAL_UART_MSPDEINIT_CB_ID :
+ huart->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
+
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
+
+ status = HAL_ERROR;
+ }
+
+ __HAL_UNLOCK(huart);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an UART Callback
+ * UART callaback is redirected to the weak predefined callback
+ * @param huart uart handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_UART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
+ * @arg @ref HAL_UART_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_UART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
+ * @arg @ref HAL_UART_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_UART_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_UART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
+ * @arg @ref HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
+ * @arg @ref HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
+ * @arg @ref HAL_UART_WAKEUP_CB_ID Wakeup Callback ID
+ * @arg @ref HAL_UART_RX_FIFO_FULL_CB_ID Rx Fifo Full Callback ID
+ * @arg @ref HAL_UART_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty Callback ID
+ * @arg @ref HAL_UART_MSPINIT_CB_ID MspInit Callback ID
+ * @arg @ref HAL_UART_MSPDEINIT_CB_ID MspDeInit Callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_UnRegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ __HAL_LOCK(huart);
+
+ if (HAL_UART_STATE_READY == huart->gState)
+ {
+ switch (CallbackID)
+ {
+ case HAL_UART_TX_HALFCOMPLETE_CB_ID :
+ huart->TxHalfCpltCallback = HAL_UART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ break;
+
+ case HAL_UART_TX_COMPLETE_CB_ID :
+ huart->TxCpltCallback = HAL_UART_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ break;
+
+ case HAL_UART_RX_HALFCOMPLETE_CB_ID :
+ huart->RxHalfCpltCallback = HAL_UART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ break;
+
+ case HAL_UART_RX_COMPLETE_CB_ID :
+ huart->RxCpltCallback = HAL_UART_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ break;
+
+ case HAL_UART_ERROR_CB_ID :
+ huart->ErrorCallback = HAL_UART_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_UART_ABORT_COMPLETE_CB_ID :
+ huart->AbortCpltCallback = HAL_UART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ break;
+
+ case HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID :
+ huart->AbortTransmitCpltCallback = HAL_UART_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
+ break;
+
+ case HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID :
+ huart->AbortReceiveCpltCallback = HAL_UART_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
+ break;
+
+ case HAL_UART_WAKEUP_CB_ID :
+ huart->WakeupCallback = HAL_UARTEx_WakeupCallback; /* Legacy weak WakeupCallback */
+ break;
+
+ case HAL_UART_RX_FIFO_FULL_CB_ID :
+ huart->RxFifoFullCallback = HAL_UARTEx_RxFifoFullCallback; /* Legacy weak RxFifoFullCallback */
+ break;
+
+ case HAL_UART_TX_FIFO_EMPTY_CB_ID :
+ huart->TxFifoEmptyCallback = HAL_UARTEx_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */
+ break;
+
+ case HAL_UART_MSPINIT_CB_ID :
+ huart->MspInitCallback = HAL_UART_MspInit; /* Legacy weak MspInitCallback */
+ break;
+
+ case HAL_UART_MSPDEINIT_CB_ID :
+ huart->MspDeInitCallback = HAL_UART_MspDeInit; /* Legacy weak MspDeInitCallback */
+ break;
+
+ default :
+ huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
+
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_UART_STATE_RESET == huart->gState)
+ {
+ switch (CallbackID)
+ {
+ case HAL_UART_MSPINIT_CB_ID :
+ huart->MspInitCallback = HAL_UART_MspInit;
+ break;
+
+ case HAL_UART_MSPDEINIT_CB_ID :
+ huart->MspDeInitCallback = HAL_UART_MspDeInit;
+ break;
+
+ default :
+ huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
+
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
+
+ status = HAL_ERROR;
+ }
+
+ __HAL_UNLOCK(huart);
+
+ return status;
+}
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Exported_Functions_Group2 IO operation functions
+ * @brief UART Transmit/Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ This subsection provides a set of functions allowing to manage the UART asynchronous
+ and Half duplex data transfers.
+
+ (#) There are two mode of transfer:
+ (+) Blocking mode: The communication is performed in polling mode.
+ The HAL status of all data processing is returned by the same function
+ after finishing transfer.
+ (+) Non-Blocking mode: The communication is performed using Interrupts
+ or DMA, These API's return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated UART IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+ The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks
+ will be executed respectively at the end of the transmit or Receive process
+ The HAL_UART_ErrorCallback()user callback will be executed when a communication error is detected
+
+ (#) Blocking mode API's are :
+ (+) HAL_UART_Transmit()
+ (+) HAL_UART_Receive()
+
+ (#) Non-Blocking mode API's with Interrupt are :
+ (+) HAL_UART_Transmit_IT()
+ (+) HAL_UART_Receive_IT()
+ (+) HAL_UART_IRQHandler()
+
+ (#) Non-Blocking mode API's with DMA are :
+ (+) HAL_UART_Transmit_DMA()
+ (+) HAL_UART_Receive_DMA()
+ (+) HAL_UART_DMAPause()
+ (+) HAL_UART_DMAResume()
+ (+) HAL_UART_DMAStop()
+
+ (#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode:
+ (+) HAL_UART_TxHalfCpltCallback()
+ (+) HAL_UART_TxCpltCallback()
+ (+) HAL_UART_RxHalfCpltCallback()
+ (+) HAL_UART_RxCpltCallback()
+ (+) HAL_UART_ErrorCallback()
+
+ (#) Non-Blocking mode transfers could be aborted using Abort API's :
+ (+) HAL_UART_Abort()
+ (+) HAL_UART_AbortTransmit()
+ (+) HAL_UART_AbortReceive()
+ (+) HAL_UART_Abort_IT()
+ (+) HAL_UART_AbortTransmit_IT()
+ (+) HAL_UART_AbortReceive_IT()
+
+ (#) For Abort services based on interrupts (HAL_UART_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
+ (+) HAL_UART_AbortCpltCallback()
+ (+) HAL_UART_AbortTransmitCpltCallback()
+ (+) HAL_UART_AbortReceiveCpltCallback()
+
+ (#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
+ Errors are handled as follows :
+ (+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
+ to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
+ Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
+ and HAL_UART_ErrorCallback() user callback is executed. Transfer is kept ongoing on UART side.
+ If user wants to abort it, Abort services should be called by user.
+ (+) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
+ This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
+ Error code is set to allow user to identify error type, and HAL_UART_ErrorCallback() user callback is executed.
+
+ -@- In the Half duplex communication, it is forbidden to run the transmit
+ and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX can't be useful.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Send an amount of data in blocking mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 provided through pData.
+ * @note When FIFO mode is enabled, writing a data in the TDR register adds one
+ * data to the TXFIFO. Write operations to the TDR register are performed
+ * when TXFNF flag is set. From hardware perspective, TXFNF flag and
+ * TXE are mapped on the same bit-field.
+ * @param huart UART handle.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be sent.
+ * @param Timeout Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint8_t *pdata8bits;
+ uint16_t *pdata16bits;
+ uint32_t tickstart;
+
+ /* Check that a Tx process is not already ongoing */
+ if (huart->gState == HAL_UART_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ __HAL_LOCK(huart);
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->gState = HAL_UART_STATE_BUSY_TX;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ huart->TxXferSize = Size;
+ huart->TxXferCount = Size;
+
+ /* In case of 9bits/No Parity transfer, pData needs to be handled as a uint16_t pointer */
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ pdata8bits = NULL;
+ pdata16bits = (uint16_t *) pData;
+ }
+ else
+ {
+ pdata8bits = pData;
+ pdata16bits = NULL;
+ }
+
+ while (huart->TxXferCount > 0U)
+ {
+ if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ if (pdata8bits == NULL)
+ {
+ huart->Instance->TDR = (uint16_t)(*pdata16bits & 0x01FFU);
+ pdata16bits++;
+ }
+ else
+ {
+ huart->Instance->TDR = (uint8_t)(*pdata8bits & 0xFFU);
+ pdata8bits++;
+ }
+ huart->TxXferCount--;
+ }
+
+ if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* At end of Tx process, restore huart->gState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 available through pData.
+ * @note When FIFO mode is enabled, the RXFNE flag is set as long as the RXFIFO
+ * is not empty. Read operations from the RDR register are performed when
+ * RXFNE flag is set. From hardware perspective, RXFNE flag and
+ * RXNE are mapped on the same bit-field.
+ * @param huart UART handle.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be received.
+ * @param Timeout Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint8_t *pdata8bits;
+ uint16_t *pdata16bits;
+ uint16_t uhMask;
+ uint32_t tickstart;
+
+ /* Check that a Rx process is not already ongoing */
+ if (huart->RxState == HAL_UART_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ __HAL_LOCK(huart);
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->RxState = HAL_UART_STATE_BUSY_RX;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ huart->RxXferSize = Size;
+ huart->RxXferCount = Size;
+
+ /* Computation of UART mask to apply to RDR register */
+ UART_MASK_COMPUTATION(huart);
+ uhMask = huart->Mask;
+
+ /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ pdata8bits = NULL;
+ pdata16bits = (uint16_t *) pData;
+ }
+ else
+ {
+ pdata8bits = pData;
+ pdata16bits = NULL;
+ }
+
+ /* as long as data have to be received */
+ while (huart->RxXferCount > 0U)
+ {
+ if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ if (pdata8bits == NULL)
+ {
+ *pdata16bits = (uint16_t)(huart->Instance->RDR & uhMask);
+ pdata16bits++;
+ }
+ else
+ {
+ *pdata8bits = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
+ pdata8bits++;
+ }
+ huart->RxXferCount--;
+ }
+
+ /* At end of Rx process, restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in interrupt mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 provided through pData.
+ * @param huart UART handle.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Tx process is not already ongoing */
+ if (huart->gState == HAL_UART_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ __HAL_LOCK(huart);
+
+ huart->pTxBuffPtr = pData;
+ huart->TxXferSize = Size;
+ huart->TxXferCount = Size;
+ huart->TxISR = NULL;
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->gState = HAL_UART_STATE_BUSY_TX;
+
+ /* Configure Tx interrupt processing */
+ if (huart->FifoMode == UART_FIFOMODE_ENABLE)
+ {
+ /* Set the Tx ISR function pointer according to the data word length */
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ huart->TxISR = UART_TxISR_16BIT_FIFOEN;
+ }
+ else
+ {
+ huart->TxISR = UART_TxISR_8BIT_FIFOEN;
+ }
+
+ __HAL_UNLOCK(huart);
+
+ /* Enable the TX FIFO threshold interrupt */
+ SET_BIT(huart->Instance->CR3, USART_CR3_TXFTIE);
+ }
+ else
+ {
+ /* Set the Tx ISR function pointer according to the data word length */
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ huart->TxISR = UART_TxISR_16BIT;
+ }
+ else
+ {
+ huart->TxISR = UART_TxISR_8BIT;
+ }
+
+ __HAL_UNLOCK(huart);
+
+ /* Enable the Transmit Data Register Empty interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in interrupt mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 available through pData.
+ * @param huart UART handle.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Rx process is not already ongoing */
+ if (huart->RxState == HAL_UART_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ __HAL_LOCK(huart);
+
+ huart->pRxBuffPtr = pData;
+ huart->RxXferSize = Size;
+ huart->RxXferCount = Size;
+ huart->RxISR = NULL;
+
+ /* Computation of UART mask to apply to RDR register */
+ UART_MASK_COMPUTATION(huart);
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->RxState = HAL_UART_STATE_BUSY_RX;
+
+ /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ /* Configure Rx interrupt processing*/
+ if ((huart->FifoMode == UART_FIFOMODE_ENABLE) && (Size >= huart->NbRxDataToProcess))
+ {
+ /* Set the Rx ISR function pointer according to the data word length */
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ huart->RxISR = UART_RxISR_16BIT_FIFOEN;
+ }
+ else
+ {
+ huart->RxISR = UART_RxISR_8BIT_FIFOEN;
+ }
+
+ __HAL_UNLOCK(huart);
+
+ /* Enable the UART Parity Error interrupt and RX FIFO Threshold interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);
+ SET_BIT(huart->Instance->CR3, USART_CR3_RXFTIE);
+ }
+ else
+ {
+ /* Set the Rx ISR function pointer according to the data word length */
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ huart->RxISR = UART_RxISR_16BIT;
+ }
+ else
+ {
+ huart->RxISR = UART_RxISR_8BIT;
+ }
+
+ __HAL_UNLOCK(huart);
+
+ /* Enable the UART Parity Error interrupt and Data Register Not Empty interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in DMA mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 provided through pData.
+ * @param huart UART handle.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Tx process is not already ongoing */
+ if (huart->gState == HAL_UART_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ __HAL_LOCK(huart);
+
+ huart->pTxBuffPtr = pData;
+ huart->TxXferSize = Size;
+ huart->TxXferCount = Size;
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->gState = HAL_UART_STATE_BUSY_TX;
+
+ if (huart->hdmatx != NULL)
+ {
+ /* Set the UART DMA transfer complete callback */
+ huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt;
+
+ /* Set the UART DMA Half transfer complete callback */
+ huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt;
+
+ /* Set the DMA error callback */
+ huart->hdmatx->XferErrorCallback = UART_DMAError;
+
+ /* Set the DMA abort callback */
+ huart->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the UART transmit DMA channel */
+ if (HAL_DMA_Start_IT(huart->hdmatx, (uint32_t)huart->pTxBuffPtr, (uint32_t)&huart->Instance->TDR, Size) != HAL_OK)
+ {
+ /* Set error code to DMA */
+ huart->ErrorCode = HAL_UART_ERROR_DMA;
+
+ __HAL_UNLOCK(huart);
+
+ /* Restore huart->gState to ready */
+ huart->gState = HAL_UART_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ /* Clear the TC flag in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_TCF);
+
+ __HAL_UNLOCK(huart);
+
+ /* Enable the DMA transfer for transmit request by setting the DMAT bit
+ in the UART CR3 register */
+ SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in DMA mode.
+ * @note When the UART parity is enabled (PCE = 1), the received data contain
+ * the parity bit (MSB position).
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 available through pData.
+ * @param huart UART handle.
+ * @param pData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ /* Check that a Rx process is not already ongoing */
+ if (huart->RxState == HAL_UART_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ __HAL_LOCK(huart);
+
+ huart->pRxBuffPtr = pData;
+ huart->RxXferSize = Size;
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->RxState = HAL_UART_STATE_BUSY_RX;
+
+ if (huart->hdmarx != NULL)
+ {
+ /* Set the UART DMA transfer complete callback */
+ huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt;
+
+ /* Set the UART DMA Half transfer complete callback */
+ huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt;
+
+ /* Set the DMA error callback */
+ huart->hdmarx->XferErrorCallback = UART_DMAError;
+
+ /* Set the DMA abort callback */
+ huart->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->RDR, (uint32_t)huart->pRxBuffPtr, Size) != HAL_OK)
+ {
+ /* Set error code to DMA */
+ huart->ErrorCode = HAL_UART_ERROR_DMA;
+
+ __HAL_UNLOCK(huart);
+
+ /* Restore huart->gState to ready */
+ huart->gState = HAL_UART_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ __HAL_UNLOCK(huart);
+
+ /* Enable the UART Parity Error Interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);
+
+ /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the DMA transfer for the receiver request by setting the DMAR bit
+ in the UART CR3 register */
+ SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Pause the DMA Transfer.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart)
+{
+ const HAL_UART_StateTypeDef gstate = huart->gState;
+ const HAL_UART_StateTypeDef rxstate = huart->RxState;
+
+ __HAL_LOCK(huart);
+
+ if ((HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) &&
+ (gstate == HAL_UART_STATE_BUSY_TX))
+ {
+ /* Disable the UART DMA Tx request */
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
+ }
+ if ((HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) &&
+ (rxstate == HAL_UART_STATE_BUSY_RX))
+ {
+ /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the UART DMA Rx request */
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+ }
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the DMA Transfer.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart)
+{
+ __HAL_LOCK(huart);
+
+ if (huart->gState == HAL_UART_STATE_BUSY_TX)
+ {
+ /* Enable the UART DMA Tx request */
+ SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
+ }
+ if (huart->RxState == HAL_UART_STATE_BUSY_RX)
+ {
+ /* Clear the Overrun flag before resuming the Rx transfer */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+
+ /* Reenable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);
+ SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the UART DMA Rx request */
+ SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+ }
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the DMA Transfer.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)
+{
+ /* The Lock is not implemented on this API to allow the user application
+ to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback() /
+ HAL_UART_TxHalfCpltCallback / HAL_UART_RxHalfCpltCallback:
+ indeed, when HAL_DMA_Abort() API is called, the DMA TX/RX Transfer or Half Transfer complete
+ interrupt is generated if the DMA transfer interruption occurs at the middle or at the end of
+ the stream and the corresponding call back is executed. */
+
+ const HAL_UART_StateTypeDef gstate = huart->gState;
+ const HAL_UART_StateTypeDef rxstate = huart->RxState;
+
+ /* Stop UART DMA Tx request if ongoing */
+ if ((HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) &&
+ (gstate == HAL_UART_STATE_BUSY_TX))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the UART DMA Tx channel */
+ if (huart->hdmatx != NULL)
+ {
+ if (HAL_DMA_Abort(huart->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(huart->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ huart->ErrorCode = HAL_UART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ UART_EndTxTransfer(huart);
+ }
+
+ /* Stop UART DMA Rx request if ongoing */
+ if ((HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) &&
+ (rxstate == HAL_UART_STATE_BUSY_RX))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the UART DMA Rx channel */
+ if (huart->hdmarx != NULL)
+ {
+ if (HAL_DMA_Abort(huart->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(huart->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ huart->ErrorCode = HAL_UART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ UART_EndRxTransfer(huart);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing transfers (blocking mode).
+ * @param huart UART handle.
+ * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable UART Interrupts (Tx and Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart)
+{
+ /* Disable TXE, TC, RXNE, PE, RXFT, TXFT and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE);
+
+ /* Disable the UART DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */
+ if (huart->hdmatx != NULL)
+ {
+ /* Set the UART DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ huart->hdmatx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(huart->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(huart->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ huart->ErrorCode = HAL_UART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Disable the UART DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */
+ if (huart->hdmarx != NULL)
+ {
+ /* Set the UART DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ huart->hdmarx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(huart->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(huart->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ huart->ErrorCode = HAL_UART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Tx and Rx transfer counters */
+ huart->TxXferCount = 0U;
+ huart->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
+
+ /* Flush the whole TX FIFO (if needed) */
+ if (huart->FifoMode == UART_FIFOMODE_ENABLE)
+ {
+ __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Discard the received data */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+
+ /* Restore huart->gState and huart->RxState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+ huart->RxState = HAL_UART_STATE_READY;
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Transmit transfer (blocking mode).
+ * @param huart UART handle.
+ * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable UART Interrupts (Tx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart)
+{
+ /* Disable TCIE, TXEIE and TXFTIE interrupts */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TCIE | USART_CR1_TXEIE_TXFNFIE));
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE);
+
+ /* Disable the UART DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */
+ if (huart->hdmatx != NULL)
+ {
+ /* Set the UART DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ huart->hdmatx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(huart->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(huart->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ huart->ErrorCode = HAL_UART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Tx transfer counter */
+ huart->TxXferCount = 0U;
+
+ /* Flush the whole TX FIFO (if needed) */
+ if (huart->FifoMode == UART_FIFOMODE_ENABLE)
+ {
+ __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Restore huart->gState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Receive transfer (blocking mode).
+ * @param huart UART handle.
+ * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable UART Interrupts (Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart)
+{
+ /* Disable PEIE, EIE, RXNEIE and RXFTIE interrupts */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE));
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE | USART_CR3_RXFTIE);
+
+ /* Disable the UART DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */
+ if (huart->hdmarx != NULL)
+ {
+ /* Set the UART DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ huart->hdmarx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(huart->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(huart->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ huart->ErrorCode = HAL_UART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Rx transfer counter */
+ huart->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
+
+ /* Discard the received data */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+
+ /* Restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing transfers (Interrupt mode).
+ * @param huart UART handle.
+ * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable UART Interrupts (Tx and Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart)
+{
+ uint32_t abortcplt = 1U;
+
+ /* Disable interrupts */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_PEIE | USART_CR1_TCIE | USART_CR1_RXNEIE_RXFNEIE | USART_CR1_TXEIE_TXFNFIE));
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE));
+
+ /* If DMA Tx and/or DMA Rx Handles are associated to UART Handle, DMA Abort complete callbacks should be initialised
+ before any call to DMA Abort functions */
+ /* DMA Tx Handle is valid */
+ if (huart->hdmatx != NULL)
+ {
+ /* Set DMA Abort Complete callback if UART DMA Tx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
+ {
+ huart->hdmatx->XferAbortCallback = UART_DMATxAbortCallback;
+ }
+ else
+ {
+ huart->hdmatx->XferAbortCallback = NULL;
+ }
+ }
+ /* DMA Rx Handle is valid */
+ if (huart->hdmarx != NULL)
+ {
+ /* Set DMA Abort Complete callback if UART DMA Rx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
+ {
+ huart->hdmarx->XferAbortCallback = UART_DMARxAbortCallback;
+ }
+ else
+ {
+ huart->hdmarx->XferAbortCallback = NULL;
+ }
+ }
+
+ /* Disable the UART DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
+ {
+ /* Disable DMA Tx at UART level */
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */
+ if (huart->hdmatx != NULL)
+ {
+ /* UART Tx DMA Abort callback has already been initialised :
+ will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK)
+ {
+ huart->hdmatx->XferAbortCallback = NULL;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+
+ /* Disable the UART DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */
+ if (huart->hdmarx != NULL)
+ {
+ /* UART Rx DMA Abort callback has already been initialised :
+ will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
+ {
+ huart->hdmarx->XferAbortCallback = NULL;
+ abortcplt = 1U;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+
+ /* if no DMA abort complete callback execution is required => call user Abort Complete callback */
+ if (abortcplt == 1U)
+ {
+ /* Reset Tx and Rx transfer counters */
+ huart->TxXferCount = 0U;
+ huart->RxXferCount = 0U;
+
+ /* Clear ISR function pointers */
+ huart->RxISR = NULL;
+ huart->TxISR = NULL;
+
+ /* Reset errorCode */
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
+
+ /* Flush the whole TX FIFO (if needed) */
+ if (huart->FifoMode == UART_FIFOMODE_ENABLE)
+ {
+ __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Discard the received data */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+
+ /* Restore huart->gState and huart->RxState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort complete callback */
+ huart->AbortCpltCallback(huart);
+#else
+ /* Call legacy weak Abort complete callback */
+ HAL_UART_AbortCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Transmit transfer (Interrupt mode).
+ * @param huart UART handle.
+ * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable UART Interrupts (Tx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart)
+{
+ /* Disable interrupts */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TCIE | USART_CR1_TXEIE_TXFNFIE));
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE);
+
+ /* Disable the UART DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */
+ if (huart->hdmatx != NULL)
+ {
+ /* Set the UART DMA Abort callback :
+ will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
+ huart->hdmatx->XferAbortCallback = UART_DMATxOnlyAbortCallback;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK)
+ {
+ /* Call Directly huart->hdmatx->XferAbortCallback function in case of error */
+ huart->hdmatx->XferAbortCallback(huart->hdmatx);
+ }
+ }
+ else
+ {
+ /* Reset Tx transfer counter */
+ huart->TxXferCount = 0U;
+
+ /* Clear TxISR function pointers */
+ huart->TxISR = NULL;
+
+ /* Restore huart->gState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Transmit Complete Callback */
+ huart->AbortTransmitCpltCallback(huart);
+#else
+ /* Call legacy weak Abort Transmit Complete Callback */
+ HAL_UART_AbortTransmitCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Reset Tx transfer counter */
+ huart->TxXferCount = 0U;
+
+ /* Clear TxISR function pointers */
+ huart->TxISR = NULL;
+
+ /* Flush the whole TX FIFO (if needed) */
+ if (huart->FifoMode == UART_FIFOMODE_ENABLE)
+ {
+ __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Restore huart->gState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Transmit Complete Callback */
+ huart->AbortTransmitCpltCallback(huart);
+#else
+ /* Call legacy weak Abort Transmit Complete Callback */
+ HAL_UART_AbortTransmitCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing Receive transfer (Interrupt mode).
+ * @param huart UART handle.
+ * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable UART Interrupts (Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart)
+{
+ /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE));
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE));
+
+ /* Disable the UART DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */
+ if (huart->hdmarx != NULL)
+ {
+ /* Set the UART DMA Abort callback :
+ will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
+ huart->hdmarx->XferAbortCallback = UART_DMARxOnlyAbortCallback;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
+ {
+ /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */
+ huart->hdmarx->XferAbortCallback(huart->hdmarx);
+ }
+ }
+ else
+ {
+ /* Reset Rx transfer counter */
+ huart->RxXferCount = 0U;
+
+ /* Clear RxISR function pointer */
+ huart->pRxBuffPtr = NULL;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
+
+ /* Discard the received data */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+
+ /* Restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Receive Complete Callback */
+ huart->AbortReceiveCpltCallback(huart);
+#else
+ /* Call legacy weak Abort Receive Complete Callback */
+ HAL_UART_AbortReceiveCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Reset Rx transfer counter */
+ huart->RxXferCount = 0U;
+
+ /* Clear RxISR function pointer */
+ huart->pRxBuffPtr = NULL;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
+
+ /* Restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Receive Complete Callback */
+ huart->AbortReceiveCpltCallback(huart);
+#else
+ /* Call legacy weak Abort Receive Complete Callback */
+ HAL_UART_AbortReceiveCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle UART interrupt request.
+ * @param huart UART handle.
+ * @retval None
+ */
+void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
+{
+ uint32_t isrflags = READ_REG(huart->Instance->ISR);
+ uint32_t cr1its = READ_REG(huart->Instance->CR1);
+ uint32_t cr3its = READ_REG(huart->Instance->CR3);
+
+ uint32_t errorflags;
+ uint32_t errorcode;
+
+ /* If no error occurs */
+ errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE | USART_ISR_RTOF));
+ if (errorflags == 0U)
+ {
+ /* UART in mode Receiver ---------------------------------------------------*/
+ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
+ && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
+ || ((cr3its & USART_CR3_RXFTIE) != 0U)))
+ {
+ if (huart->RxISR != NULL)
+ {
+ huart->RxISR(huart);
+ }
+ return;
+ }
+ }
+
+ /* If some errors occur */
+ if ((errorflags != 0U)
+ && ((((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != 0U)
+ || ((cr1its & (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_RTOIE)) != 0U))))
+ {
+ /* UART parity error interrupt occurred -------------------------------------*/
+ if (((isrflags & USART_ISR_PE) != 0U) && ((cr1its & USART_CR1_PEIE) != 0U))
+ {
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_PEF);
+
+ huart->ErrorCode |= HAL_UART_ERROR_PE;
+ }
+
+ /* UART frame error interrupt occurred --------------------------------------*/
+ if (((isrflags & USART_ISR_FE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
+ {
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_FEF);
+
+ huart->ErrorCode |= HAL_UART_ERROR_FE;
+ }
+
+ /* UART noise error interrupt occurred --------------------------------------*/
+ if (((isrflags & USART_ISR_NE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
+ {
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_NEF);
+
+ huart->ErrorCode |= HAL_UART_ERROR_NE;
+ }
+
+ /* UART Over-Run interrupt occurred -----------------------------------------*/
+ if (((isrflags & USART_ISR_ORE) != 0U)
+ && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) ||
+ ((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != 0U)))
+ {
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+
+ huart->ErrorCode |= HAL_UART_ERROR_ORE;
+ }
+
+ /* UART Receiver Timeout interrupt occurred ---------------------------------*/
+ if (((isrflags & USART_ISR_RTOF) != 0U) && ((cr1its & USART_CR1_RTOIE) != 0U))
+ {
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_RTOF);
+
+ huart->ErrorCode |= HAL_UART_ERROR_RTO;
+ }
+
+ /* Call UART Error Call back function if need be ----------------------------*/
+ if (huart->ErrorCode != HAL_UART_ERROR_NONE)
+ {
+ /* UART in mode Receiver --------------------------------------------------*/
+ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
+ && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
+ || ((cr3its & USART_CR3_RXFTIE) != 0U)))
+ {
+ if (huart->RxISR != NULL)
+ {
+ huart->RxISR(huart);
+ }
+ }
+
+ /* If Error is to be considered as blocking :
+ - Receiver Timeout error in Reception
+ - Overrun error in Reception
+ - any error occurs in DMA mode reception
+ */
+ errorcode = huart->ErrorCode;
+ if ((HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) ||
+ ((errorcode & (HAL_UART_ERROR_RTO | HAL_UART_ERROR_ORE)) != 0U))
+ {
+ /* Blocking error : transfer is aborted
+ Set the UART state ready to be able to start again the process,
+ Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
+ UART_EndRxTransfer(huart);
+
+ /* Disable the UART DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the UART DMA Rx channel */
+ if (huart->hdmarx != NULL)
+ {
+ /* Set the UART DMA Abort callback :
+ will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
+ huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
+ {
+ /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */
+ huart->hdmarx->XferAbortCallback(huart->hdmarx);
+ }
+ }
+ else
+ {
+ /* Call user error callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ huart->ErrorCallback(huart);
+#else
+ /*Call legacy weak error callback*/
+ HAL_UART_ErrorCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+
+ }
+ }
+ else
+ {
+ /* Call user error callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ huart->ErrorCallback(huart);
+#else
+ /*Call legacy weak error callback*/
+ HAL_UART_ErrorCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Non Blocking error : transfer could go on.
+ Error is notified to user through user error callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ huart->ErrorCallback(huart);
+#else
+ /*Call legacy weak error callback*/
+ HAL_UART_ErrorCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ }
+ }
+ return;
+
+ } /* End if some error occurs */
+
+ /* UART wakeup from Stop mode interrupt occurred ---------------------------*/
+ if (((isrflags & USART_ISR_WUF) != 0U) && ((cr3its & USART_CR3_WUFIE) != 0U))
+ {
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_WUF);
+
+ /* UART Rx state is not reset as a reception process might be ongoing.
+ If UART handle state fields need to be reset to READY, this could be done in Wakeup callback */
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Wakeup Callback */
+ huart->WakeupCallback(huart);
+#else
+ /* Call legacy weak Wakeup Callback */
+ HAL_UARTEx_WakeupCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ return;
+ }
+
+ /* UART in mode Transmitter ------------------------------------------------*/
+ if (((isrflags & USART_ISR_TXE_TXFNF) != 0U)
+ && (((cr1its & USART_CR1_TXEIE_TXFNFIE) != 0U)
+ || ((cr3its & USART_CR3_TXFTIE) != 0U)))
+ {
+ if (huart->TxISR != NULL)
+ {
+ huart->TxISR(huart);
+ }
+ return;
+ }
+
+ /* UART in mode Transmitter (transmission end) -----------------------------*/
+ if (((isrflags & USART_ISR_TC) != 0U) && ((cr1its & USART_CR1_TCIE) != 0U))
+ {
+ UART_EndTransmit_IT(huart);
+ return;
+ }
+
+ /* UART TX Fifo Empty occurred ----------------------------------------------*/
+ if (((isrflags & USART_ISR_TXFE) != 0U) && ((cr1its & USART_CR1_TXFEIE) != 0U))
+ {
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Fifo Empty Callback */
+ huart->TxFifoEmptyCallback(huart);
+#else
+ /* Call legacy weak Tx Fifo Empty Callback */
+ HAL_UARTEx_TxFifoEmptyCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ return;
+ }
+
+ /* UART RX Fifo Full occurred ----------------------------------------------*/
+ if (((isrflags & USART_ISR_RXFF) != 0U) && ((cr1its & USART_CR1_RXFFIE) != 0U))
+ {
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Fifo Full Callback */
+ huart->RxFifoFullCallback(huart);
+#else
+ /* Call legacy weak Rx Fifo Full Callback */
+ HAL_UARTEx_RxFifoFullCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ return;
+ }
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_TxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_UART_TxHalfCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_RxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Rx Half Transfer completed callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_UART_RxHalfCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief UART error callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_ErrorCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief UART Abort Complete callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_AbortCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief UART Abort Complete callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief UART Abort Receive Complete callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_AbortReceiveCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions
+ * @brief UART control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the UART.
+ (+) HAL_UART_ReceiverTimeout_Config() API allows to configure the receiver timeout value on the fly
+ (+) HAL_UART_EnableReceiverTimeout() API enables the receiver timeout feature
+ (+) HAL_UART_DisableReceiverTimeout() API disables the receiver timeout feature
+ (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode
+ (+) HAL_MultiProcessor_DisableMuteMode() API disables mute mode
+ (+) HAL_MultiProcessor_EnterMuteMode() API enters mute mode
+ (+) UART_SetConfig() API configures the UART peripheral
+ (+) UART_AdvFeatureConfig() API optionally configures the UART advanced features
+ (+) UART_CheckIdleState() API ensures that TEACK and/or REACK are set after initialization
+ (+) HAL_HalfDuplex_EnableTransmitter() API disables receiver and enables transmitter
+ (+) HAL_HalfDuplex_EnableReceiver() API disables transmitter and enables receiver
+ (+) HAL_LIN_SendBreak() API transmits the break characters
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Update on the fly the receiver timeout value in RTOR register.
+ * @param huart Pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @param TimeoutValue receiver timeout value in number of baud blocks. The timeout
+ * value must be less or equal to 0x0FFFFFFFF.
+ * @retval None
+ */
+void HAL_UART_ReceiverTimeout_Config(UART_HandleTypeDef *huart, uint32_t TimeoutValue)
+{
+ if (!(IS_LPUART_INSTANCE(huart->Instance)))
+ {
+ assert_param(IS_UART_RECEIVER_TIMEOUT_VALUE(TimeoutValue));
+ MODIFY_REG(huart->Instance->RTOR, USART_RTOR_RTO, TimeoutValue);
+ }
+}
+
+/**
+ * @brief Enable the UART receiver timeout feature.
+ * @param huart Pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_EnableReceiverTimeout(UART_HandleTypeDef *huart)
+{
+ if (!(IS_LPUART_INSTANCE(huart->Instance)))
+ {
+ if (huart->gState == HAL_UART_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Set the USART RTOEN bit */
+ SET_BIT(huart->Instance->CR2, USART_CR2_RTOEN);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable the UART receiver timeout feature.
+ * @param huart Pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_DisableReceiverTimeout(UART_HandleTypeDef *huart)
+{
+ if (!(IS_LPUART_INSTANCE(huart->Instance)))
+ {
+ if (huart->gState == HAL_UART_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Clear the USART RTOEN bit */
+ CLEAR_BIT(huart->Instance->CR2, USART_CR2_RTOEN);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable UART in mute mode (does not mean UART enters mute mode;
+ * to enter mute mode, HAL_MultiProcessor_EnterMuteMode() API must be called).
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MultiProcessor_EnableMuteMode(UART_HandleTypeDef *huart)
+{
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Enable USART mute mode by setting the MME bit in the CR1 register */
+ SET_BIT(huart->Instance->CR1, USART_CR1_MME);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ return (UART_CheckIdleState(huart));
+}
+
+/**
+ * @brief Disable UART mute mode (does not mean the UART actually exits mute mode
+ * as it may not have been in mute mode at this very moment).
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MultiProcessor_DisableMuteMode(UART_HandleTypeDef *huart)
+{
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Disable USART mute mode by clearing the MME bit in the CR1 register */
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_MME);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ return (UART_CheckIdleState(huart));
+}
+
+/**
+ * @brief Enter UART mute mode (means UART actually enters mute mode).
+ * @note To exit from mute mode, HAL_MultiProcessor_DisableMuteMode() API must be called.
+ * @param huart UART handle.
+ * @retval None
+ */
+void HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart)
+{
+ __HAL_UART_SEND_REQ(huart, UART_MUTE_MODE_REQUEST);
+}
+
+/**
+ * @brief Enable the UART transmitter and disable the UART receiver.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart)
+{
+ __HAL_LOCK(huart);
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Clear TE and RE bits */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));
+
+ /* Enable the USART's transmit interface by setting the TE bit in the USART CR1 register */
+ SET_BIT(huart->Instance->CR1, USART_CR1_TE);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the UART receiver and disable the UART transmitter.
+ * @param huart UART handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart)
+{
+ __HAL_LOCK(huart);
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Clear TE and RE bits */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));
+
+ /* Enable the USART's receive interface by setting the RE bit in the USART CR1 register */
+ SET_BIT(huart->Instance->CR1, USART_CR1_RE);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Transmit break characters.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart)
+{
+ /* Check the parameters */
+ assert_param(IS_UART_LIN_INSTANCE(huart->Instance));
+
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Send break characters */
+ __HAL_UART_SEND_REQ(huart, UART_SENDBREAK_REQUEST);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Error functions
+ * @brief UART Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Error functions #####
+ ==============================================================================
+ [..]
+ This subsection provides functions allowing to :
+ (+) Return the UART handle state.
+ (+) Return the UART handle error code
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the UART handle state.
+ * @param huart Pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART.
+ * @retval HAL state
+ */
+HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart)
+{
+ uint32_t temp1;
+ uint32_t temp2;
+ temp1 = huart->gState;
+ temp2 = huart->RxState;
+
+ return (HAL_UART_StateTypeDef)(temp1 | temp2);
+}
+
+/**
+ * @brief Return the UART handle error code.
+ * @param huart Pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART.
+ * @retval UART Error Code
+ */
+uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart)
+{
+ return huart->ErrorCode;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Private_Functions UART Private Functions
+ * @{
+ */
+
+/**
+ * @brief Initialize the callbacks to their default values.
+ * @param huart UART handle.
+ * @retval none
+ */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+void UART_InitCallbacksToDefault(UART_HandleTypeDef *huart)
+{
+ /* Init the UART Callback settings */
+ huart->TxHalfCpltCallback = HAL_UART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ huart->TxCpltCallback = HAL_UART_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ huart->RxHalfCpltCallback = HAL_UART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ huart->RxCpltCallback = HAL_UART_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ huart->ErrorCallback = HAL_UART_ErrorCallback; /* Legacy weak ErrorCallback */
+ huart->AbortCpltCallback = HAL_UART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ huart->AbortTransmitCpltCallback = HAL_UART_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
+ huart->AbortReceiveCpltCallback = HAL_UART_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
+ huart->WakeupCallback = HAL_UARTEx_WakeupCallback; /* Legacy weak WakeupCallback */
+ huart->RxFifoFullCallback = HAL_UARTEx_RxFifoFullCallback; /* Legacy weak RxFifoFullCallback */
+ huart->TxFifoEmptyCallback = HAL_UARTEx_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */
+
+}
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+
+/**
+ * @brief Configure the UART peripheral.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart)
+{
+ uint32_t tmpreg;
+ uint16_t brrtemp;
+ UART_ClockSourceTypeDef clocksource;
+ uint32_t usartdiv = 0x00000000U;
+ HAL_StatusTypeDef ret = HAL_OK;
+ uint32_t lpuart_ker_ck_pres = 0x00000000U;
+ PLL2_ClocksTypeDef pll2_clocks;
+ PLL3_ClocksTypeDef pll3_clocks;
+ uint32_t pclk;
+
+ /* Check the parameters */
+ assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate));
+ assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));
+ if (UART_INSTANCE_LOWPOWER(huart))
+ {
+ assert_param(IS_LPUART_STOPBITS(huart->Init.StopBits));
+ }
+ else
+ {
+ assert_param(IS_UART_STOPBITS(huart->Init.StopBits));
+ assert_param(IS_UART_ONE_BIT_SAMPLE(huart->Init.OneBitSampling));
+ }
+
+ assert_param(IS_UART_PARITY(huart->Init.Parity));
+ assert_param(IS_UART_MODE(huart->Init.Mode));
+ assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl));
+ assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling));
+ assert_param(IS_UART_PRESCALER(huart->Init.ClockPrescaler));
+
+ /*-------------------------- USART CR1 Configuration -----------------------*/
+ /* Clear M, PCE, PS, TE, RE and OVER8 bits and configure
+ * the UART Word Length, Parity, Mode and oversampling:
+ * set the M bits according to huart->Init.WordLength value
+ * set PCE and PS bits according to huart->Init.Parity value
+ * set TE and RE bits according to huart->Init.Mode value
+ * set OVER8 bit according to huart->Init.OverSampling value */
+ tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling ;
+ tmpreg |= (uint32_t)huart->FifoMode;
+ MODIFY_REG(huart->Instance->CR1, USART_CR1_FIELDS, tmpreg);
+
+ /*-------------------------- USART CR2 Configuration -----------------------*/
+ /* Configure the UART Stop Bits: Set STOP[13:12] bits according
+ * to huart->Init.StopBits value */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits);
+
+ /*-------------------------- USART CR3 Configuration -----------------------*/
+ /* Configure
+ * - UART HardWare Flow Control: set CTSE and RTSE bits according
+ * to huart->Init.HwFlowCtl value
+ * - one-bit sampling method versus three samples' majority rule according
+ * to huart->Init.OneBitSampling (not applicable to LPUART) */
+ tmpreg = (uint32_t)huart->Init.HwFlowCtl;
+
+ if (!(UART_INSTANCE_LOWPOWER(huart)))
+ {
+ tmpreg |= huart->Init.OneBitSampling;
+ }
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_FIELDS, tmpreg);
+
+ /*-------------------------- USART PRESC Configuration -----------------------*/
+ /* Configure
+ * - UART Clock Prescaler : set PRESCALER according to huart->Init.ClockPrescaler value */
+ MODIFY_REG(huart->Instance->PRESC, USART_PRESC_PRESCALER, huart->Init.ClockPrescaler);
+
+ /*-------------------------- USART BRR Configuration -----------------------*/
+ UART_GETCLOCKSOURCE(huart, clocksource);
+
+ /* Check LPUART instance */
+ if (UART_INSTANCE_LOWPOWER(huart))
+ {
+ /* Retrieve frequency clock */
+ switch (clocksource)
+ {
+ case UART_CLOCKSOURCE_D3PCLK1:
+ lpuart_ker_ck_pres = (HAL_RCCEx_GetD3PCLK1Freq() / UART_GET_DIV_FACTOR(huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_PLL2:
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ lpuart_ker_ck_pres = (pll2_clocks.PLL2_Q_Frequency / UART_GET_DIV_FACTOR(huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_PLL3:
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ lpuart_ker_ck_pres = (pll3_clocks.PLL3_Q_Frequency / UART_GET_DIV_FACTOR(huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_HSI:
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ lpuart_ker_ck_pres = ((uint32_t)(HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3U)) / UART_GET_DIV_FACTOR(huart->Init.ClockPrescaler));
+ }
+ else
+ {
+ lpuart_ker_ck_pres = ((uint32_t) HSI_VALUE / UART_GET_DIV_FACTOR(huart->Init.ClockPrescaler));
+ }
+ break;
+ case UART_CLOCKSOURCE_CSI:
+ lpuart_ker_ck_pres = ((uint32_t)CSI_VALUE / UART_GET_DIV_FACTOR(huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_LSE:
+ lpuart_ker_ck_pres = ((uint32_t)LSE_VALUE / UART_GET_DIV_FACTOR(huart->Init.ClockPrescaler));
+ break;
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ /* if proper clock source reported */
+ if (lpuart_ker_ck_pres != 0U)
+ {
+ /* ensure that Frequency clock is in the range [3 * baudrate, 4096 * baudrate] */
+ if ((lpuart_ker_ck_pres < (3U * huart->Init.BaudRate)) ||
+ (lpuart_ker_ck_pres > (4096U * huart->Init.BaudRate)))
+ {
+ ret = HAL_ERROR;
+ }
+ else
+ {
+ switch (clocksource)
+ {
+ case UART_CLOCKSOURCE_D3PCLK1:
+ pclk = HAL_RCCEx_GetD3PCLK1Freq();
+ usartdiv = (uint32_t)(UART_DIV_LPUART(pclk, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_PLL2:
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ usartdiv = (uint32_t)(UART_DIV_LPUART(pll2_clocks.PLL2_Q_Frequency, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_PLL3:
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ usartdiv = (uint32_t)(UART_DIV_LPUART(pll3_clocks.PLL3_Q_Frequency, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_HSI:
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ usartdiv = (uint32_t)(UART_DIV_LPUART((uint32_t)(HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3U)), huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ }
+ else
+ {
+ usartdiv = (uint32_t)(UART_DIV_LPUART(HSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ }
+ break;
+ case UART_CLOCKSOURCE_CSI:
+ usartdiv = (uint32_t)(UART_DIV_LPUART(CSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_LSE:
+ usartdiv = (uint32_t)(UART_DIV_LPUART(LSE_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ /* It is forbidden to write values lower than 0x300 in the LPUART_BRR register */
+ if ((usartdiv >= LPUART_BRR_MIN) && (usartdiv <= LPUART_BRR_MAX))
+ {
+ huart->Instance->BRR = usartdiv;
+ }
+ else
+ {
+ ret = HAL_ERROR;
+ }
+ } /* if ( (lpuart_ker_ck_pres < (3 * huart->Init.BaudRate) ) || (lpuart_ker_ck_pres > (4096 * huart->Init.BaudRate) )) */
+ } /* if (lpuart_ker_ck_pres != 0) */
+ }
+ /* Check UART Over Sampling to set Baud Rate Register */
+ else if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
+ {
+ switch (clocksource)
+ {
+ case UART_CLOCKSOURCE_D2PCLK1:
+ pclk = HAL_RCC_GetPCLK1Freq();
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(pclk, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_D2PCLK2:
+ pclk = HAL_RCC_GetPCLK2Freq();
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(pclk, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_PLL2:
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(pll2_clocks.PLL2_Q_Frequency, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_PLL3:
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(pll3_clocks.PLL3_Q_Frequency, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_HSI:
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8((HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3U)), huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ }
+ else
+ {
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ }
+ break;
+ case UART_CLOCKSOURCE_CSI:
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(CSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_LSE:
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8((uint32_t)LSE_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ /* USARTDIV must be greater than or equal to 0d16 */
+ if ((usartdiv >= UART_BRR_MIN) && (usartdiv <= UART_BRR_MAX))
+ {
+ brrtemp = (uint16_t)(usartdiv & 0xFFF0U);
+ brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U);
+ huart->Instance->BRR = brrtemp;
+ }
+ else
+ {
+ ret = HAL_ERROR;
+ }
+ }
+ else
+ {
+ switch (clocksource)
+ {
+ case UART_CLOCKSOURCE_D2PCLK1:
+ pclk = HAL_RCC_GetPCLK1Freq();
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING16(pclk, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_D2PCLK2:
+ pclk = HAL_RCC_GetPCLK2Freq();
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING16(pclk, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_PLL2:
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING16(pll2_clocks.PLL2_Q_Frequency, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_PLL3:
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING16(pll3_clocks.PLL3_Q_Frequency, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_HSI:
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING16((HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3U)), huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ }
+ else
+ {
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ }
+ break;
+ case UART_CLOCKSOURCE_CSI:
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING16(CSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ case UART_CLOCKSOURCE_LSE:
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING16((uint32_t)LSE_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler));
+ break;
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ /* USARTDIV must be greater than or equal to 0d16 */
+ if ((usartdiv >= UART_BRR_MIN) && (usartdiv <= UART_BRR_MAX))
+ {
+ huart->Instance->BRR = usartdiv;
+ }
+ else
+ {
+ ret = HAL_ERROR;
+ }
+ }
+
+ /* Initialize the number of data to process during RX/TX ISR execution */
+ huart->NbTxDataToProcess = 1;
+ huart->NbRxDataToProcess = 1;
+
+ /* Clear ISR function pointers */
+ huart->RxISR = NULL;
+ huart->TxISR = NULL;
+
+ return ret;
+}
+
+/**
+ * @brief Configure the UART peripheral advanced features.
+ * @param huart UART handle.
+ * @retval None
+ */
+void UART_AdvFeatureConfig(UART_HandleTypeDef *huart)
+{
+ /* Check whether the set of advanced features to configure is properly set */
+ assert_param(IS_UART_ADVFEATURE_INIT(huart->AdvancedInit.AdvFeatureInit));
+
+ /* if required, configure TX pin active level inversion */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_TXINVERT_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_TXINV(huart->AdvancedInit.TxPinLevelInvert));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_TXINV, huart->AdvancedInit.TxPinLevelInvert);
+ }
+
+ /* if required, configure RX pin active level inversion */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXINVERT_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_RXINV(huart->AdvancedInit.RxPinLevelInvert));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_RXINV, huart->AdvancedInit.RxPinLevelInvert);
+ }
+
+ /* if required, configure data inversion */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DATAINVERT_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_DATAINV(huart->AdvancedInit.DataInvert));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_DATAINV, huart->AdvancedInit.DataInvert);
+ }
+
+ /* if required, configure RX/TX pins swap */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_SWAP_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_SWAP(huart->AdvancedInit.Swap));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_SWAP, huart->AdvancedInit.Swap);
+ }
+
+ /* if required, configure RX overrun detection disabling */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXOVERRUNDISABLE_INIT))
+ {
+ assert_param(IS_UART_OVERRUN(huart->AdvancedInit.OverrunDisable));
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_OVRDIS, huart->AdvancedInit.OverrunDisable);
+ }
+
+ /* if required, configure DMA disabling on reception error */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DMADISABLEONERROR_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_DMAONRXERROR(huart->AdvancedInit.DMADisableonRxError));
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_DDRE, huart->AdvancedInit.DMADisableonRxError);
+ }
+
+ /* if required, configure auto Baud rate detection scheme */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_AUTOBAUDRATE_INIT))
+ {
+ assert_param(IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(huart->Instance));
+ assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATE(huart->AdvancedInit.AutoBaudRateEnable));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ABREN, huart->AdvancedInit.AutoBaudRateEnable);
+ /* set auto Baudrate detection parameters if detection is enabled */
+ if (huart->AdvancedInit.AutoBaudRateEnable == UART_ADVFEATURE_AUTOBAUDRATE_ENABLE)
+ {
+ assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(huart->AdvancedInit.AutoBaudRateMode));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ABRMODE, huart->AdvancedInit.AutoBaudRateMode);
+ }
+ }
+
+ /* if required, configure MSB first on communication line */
+ if (HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_MSBFIRST_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_MSBFIRST(huart->AdvancedInit.MSBFirst));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_MSBFIRST, huart->AdvancedInit.MSBFirst);
+ }
+}
+
+/**
+ * @brief Check the UART Idle State.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart)
+{
+ uint32_t tickstart;
+
+ /* Initialize the UART ErrorCode */
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Check if the Transmitter is enabled */
+ if ((huart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE)
+ {
+ /* Wait until TEACK flag is set */
+ if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_TEACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check if the Receiver is enabled */
+ if ((huart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE)
+ {
+ /* Wait until REACK flag is set */
+ if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Initialize the UART State */
+ huart->gState = HAL_UART_STATE_READY;
+ huart->RxState = HAL_UART_STATE_READY;
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle UART Communication Timeout.
+ * @param huart UART handle.
+ * @param Flag Specifies the UART flag to check
+ * @param Status Flag status (SET or RESET)
+ * @param Tickstart Tick start value
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status,
+ uint32_t Tickstart, uint32_t Timeout)
+{
+ /* Wait until flag is set */
+ while ((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE));
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ huart->gState = HAL_UART_STATE_READY;
+ huart->RxState = HAL_UART_STATE_READY;
+
+ __HAL_UNLOCK(huart);
+
+ return HAL_TIMEOUT;
+ }
+
+ if (READ_BIT(huart->Instance->CR1, USART_CR1_RE) != 0U)
+ {
+ if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RTOF) == SET)
+ {
+ /* Clear Receiver Timeout flag*/
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_RTOF);
+
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE));
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ huart->gState = HAL_UART_STATE_READY;
+ huart->RxState = HAL_UART_STATE_READY;
+ huart->ErrorCode = HAL_UART_ERROR_RTO;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+
+/**
+ * @brief End ongoing Tx transfer on UART peripheral (following error detection or Transmit completion).
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_EndTxTransfer(UART_HandleTypeDef *huart)
+{
+ /* Disable TXEIE, TCIE, TXFT interrupts */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE));
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_TXFTIE));
+
+ /* At end of Tx process, restore huart->gState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+}
+
+
+/**
+ * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion).
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_EndRxTransfer(UART_HandleTypeDef *huart)
+{
+ /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE));
+
+ /* At end of Rx process, restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Reset RxIsr function pointer */
+ huart->RxISR = NULL;
+}
+
+
+/**
+ * @brief DMA UART transmit process complete callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
+
+ /* DMA Normal mode */
+ if (hdma->Init.Mode != DMA_CIRCULAR)
+ {
+ huart->TxXferCount = 0U;
+
+ /* Disable the DMA transfer for transmit request by resetting the DMAT bit
+ in the UART CR3 register */
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
+
+ /* Enable the UART Transmit Complete Interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
+ }
+ /* DMA Circular mode */
+ else
+ {
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered Tx complete callback*/
+ huart->TxCpltCallback(huart);
+#else
+ /*Call legacy weak Tx complete callback*/
+ HAL_UART_TxCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief DMA UART transmit process half complete callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered Tx Half complete callback*/
+ huart->TxHalfCpltCallback(huart);
+#else
+ /*Call legacy weak Tx Half complete callback*/
+ HAL_UART_TxHalfCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA UART receive process complete callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
+
+ /* DMA Normal mode */
+ if (hdma->Init.Mode != DMA_CIRCULAR)
+ {
+ huart->RxXferCount = 0U;
+
+ /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the DMA transfer for the receiver request by resetting the DMAR bit
+ in the UART CR3 register */
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
+
+ /* At end of Rx process, restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+ }
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered Rx complete callback*/
+ huart->RxCpltCallback(huart);
+#else
+ /*Call legacy weak Rx complete callback*/
+ HAL_UART_RxCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA UART receive process half complete callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered Rx Half complete callback*/
+ huart->RxHalfCpltCallback(huart);
+#else
+ /*Call legacy weak Rx Half complete callback*/
+ HAL_UART_RxHalfCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA UART communication error callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMAError(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
+
+ const HAL_UART_StateTypeDef gstate = huart->gState;
+ const HAL_UART_StateTypeDef rxstate = huart->RxState;
+
+ /* Stop UART DMA Tx request if ongoing */
+ if ((HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) &&
+ (gstate == HAL_UART_STATE_BUSY_TX))
+ {
+ huart->TxXferCount = 0U;
+ UART_EndTxTransfer(huart);
+ }
+
+ /* Stop UART DMA Rx request if ongoing */
+ if ((HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) &&
+ (rxstate == HAL_UART_STATE_BUSY_RX))
+ {
+ huart->RxXferCount = 0U;
+ UART_EndRxTransfer(huart);
+ }
+
+ huart->ErrorCode |= HAL_UART_ERROR_DMA;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ huart->ErrorCallback(huart);
+#else
+ /*Call legacy weak error callback*/
+ HAL_UART_ErrorCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA UART communication abort callback, when initiated by HAL services on Error
+ * (To be called at end of DMA Abort procedure following error occurrence).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
+ huart->RxXferCount = 0U;
+ huart->TxXferCount = 0U;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered error callback*/
+ huart->ErrorCallback(huart);
+#else
+ /*Call legacy weak error callback*/
+ HAL_UART_ErrorCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA UART Tx communication abort callback, when initiated by user
+ * (To be called at end of DMA Tx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Rx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
+
+ huart->hdmatx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (huart->hdmarx != NULL)
+ {
+ if (huart->hdmarx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
+ huart->TxXferCount = 0U;
+ huart->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
+
+ /* Flush the whole TX FIFO (if needed) */
+ if (huart->FifoMode == UART_FIFOMODE_ENABLE)
+ {
+ __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Restore huart->gState and huart->RxState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort complete callback */
+ huart->AbortCpltCallback(huart);
+#else
+ /* Call legacy weak Abort complete callback */
+ HAL_UART_AbortCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+
+/**
+ * @brief DMA UART Rx communication abort callback, when initiated by user
+ * (To be called at end of DMA Rx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Tx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
+
+ huart->hdmarx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (huart->hdmatx != NULL)
+ {
+ if (huart->hdmatx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
+ huart->TxXferCount = 0U;
+ huart->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
+
+ /* Discard the received data */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+
+ /* Restore huart->gState and huart->RxState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort complete callback */
+ huart->AbortCpltCallback(huart);
+#else
+ /* Call legacy weak Abort complete callback */
+ HAL_UART_AbortCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+
+/**
+ * @brief DMA UART Tx communication abort callback, when initiated by user by a call to
+ * HAL_UART_AbortTransmit_IT API (Abort only Tx transfer)
+ * (This callback is executed at end of DMA Tx Abort procedure following user abort request,
+ * and leads to user Tx Abort Complete callback execution).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
+
+ huart->TxXferCount = 0U;
+
+ /* Flush the whole TX FIFO (if needed) */
+ if (huart->FifoMode == UART_FIFOMODE_ENABLE)
+ {
+ __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Restore huart->gState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Transmit Complete Callback */
+ huart->AbortTransmitCpltCallback(huart);
+#else
+ /* Call legacy weak Abort Transmit Complete Callback */
+ HAL_UART_AbortTransmitCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA UART Rx communication abort callback, when initiated by user by a call to
+ * HAL_UART_AbortReceive_IT API (Abort only Rx transfer)
+ * (This callback is executed at end of DMA Rx Abort procedure following user abort request,
+ * and leads to user Rx Abort Complete callback execution).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ huart->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
+
+ /* Discard the received data */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+
+ /* Restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Receive Complete Callback */
+ huart->AbortReceiveCpltCallback(huart);
+#else
+ /* Call legacy weak Abort Receive Complete Callback */
+ HAL_UART_AbortReceiveCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief TX interrrupt handler for 7 or 8 bits data word length .
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_UART_Transmit_IT().
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_TxISR_8BIT(UART_HandleTypeDef *huart)
+{
+ /* Check that a Tx process is ongoing */
+ if (huart->gState == HAL_UART_STATE_BUSY_TX)
+ {
+ if (huart->TxXferCount == 0U)
+ {
+ /* Disable the UART Transmit Data Register Empty Interrupt */
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
+
+ /* Enable the UART Transmit Complete Interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
+ }
+ else
+ {
+ huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr & (uint8_t)0xFF);
+ huart->pTxBuffPtr++;
+ huart->TxXferCount--;
+ }
+ }
+}
+
+/**
+ * @brief TX interrrupt handler for 9 bits data word length.
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_UART_Transmit_IT().
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_TxISR_16BIT(UART_HandleTypeDef *huart)
+{
+ uint16_t *tmp;
+
+ /* Check that a Tx process is ongoing */
+ if (huart->gState == HAL_UART_STATE_BUSY_TX)
+ {
+ if (huart->TxXferCount == 0U)
+ {
+ /* Disable the UART Transmit Data Register Empty Interrupt */
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
+
+ /* Enable the UART Transmit Complete Interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
+ }
+ else
+ {
+ tmp = (uint16_t *) huart->pTxBuffPtr;
+ huart->Instance->TDR = (((uint32_t)(*tmp)) & 0x01FFUL);
+ huart->pTxBuffPtr += 2U;
+ huart->TxXferCount--;
+ }
+ }
+}
+
+/**
+ * @brief TX interrrupt handler for 7 or 8 bits data word length and FIFO mode is enabled.
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_UART_Transmit_IT().
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_TxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart)
+{
+ uint16_t nb_tx_data;
+
+ /* Check that a Tx process is ongoing */
+ if (huart->gState == HAL_UART_STATE_BUSY_TX)
+ {
+ for (nb_tx_data = huart->NbTxDataToProcess ; nb_tx_data > 0U ; nb_tx_data--)
+ {
+ if (huart->TxXferCount == 0U)
+ {
+ /* Disable the TX FIFO threshold interrupt */
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE);
+
+ /* Enable the UART Transmit Complete Interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
+
+ break; /* force exit loop */
+ }
+ else if (READ_BIT(huart->Instance->ISR, USART_ISR_TXE_TXFNF) != 0U)
+ {
+ huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr & (uint8_t)0xFF);
+ huart->pTxBuffPtr++;
+ huart->TxXferCount--;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+}
+
+/**
+ * @brief TX interrrupt handler for 9 bits data word length and FIFO mode is enabled.
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_UART_Transmit_IT().
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_TxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart)
+{
+ uint16_t *tmp;
+ uint16_t nb_tx_data;
+
+ /* Check that a Tx process is ongoing */
+ if (huart->gState == HAL_UART_STATE_BUSY_TX)
+ {
+ for (nb_tx_data = huart->NbTxDataToProcess ; nb_tx_data > 0U ; nb_tx_data--)
+ {
+ if (huart->TxXferCount == 0U)
+ {
+ /* Disable the TX FIFO threshold interrupt */
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE);
+
+ /* Enable the UART Transmit Complete Interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
+
+ break; /* force exit loop */
+ }
+ else if (READ_BIT(huart->Instance->ISR, USART_ISR_TXE_TXFNF) != 0U)
+ {
+ tmp = (uint16_t *) huart->pTxBuffPtr;
+ huart->Instance->TDR = (((uint32_t)(*tmp)) & 0x01FFUL);
+ huart->pTxBuffPtr += 2U;
+ huart->TxXferCount--;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+}
+
+/**
+ * @brief Wrap up transmission in non-blocking mode.
+ * @param huart pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @retval None
+ */
+static void UART_EndTransmit_IT(UART_HandleTypeDef *huart)
+{
+ /* Disable the UART Transmit Complete Interrupt */
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_TCIE);
+
+ /* Tx process is ended, restore huart->gState to Ready */
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* Cleat TxISR function pointer */
+ huart->TxISR = NULL;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered Tx complete callback*/
+ huart->TxCpltCallback(huart);
+#else
+ /*Call legacy weak Tx complete callback*/
+ HAL_UART_TxCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief RX interrrupt handler for 7 or 8 bits data word length .
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_RxISR_8BIT(UART_HandleTypeDef *huart)
+{
+ uint16_t uhMask = huart->Mask;
+ uint16_t uhdata;
+
+ /* Check that a Rx process is ongoing */
+ if (huart->RxState == HAL_UART_STATE_BUSY_RX)
+ {
+ uhdata = (uint16_t) READ_REG(huart->Instance->RDR);
+ *huart->pRxBuffPtr = (uint8_t)(uhdata & (uint8_t)uhMask);
+ huart->pRxBuffPtr++;
+ huart->RxXferCount--;
+
+ if (huart->RxXferCount == 0U)
+ {
+ /* Disable the UART Parity Error Interrupt and RXNE interrupts */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+
+ /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ /* Rx process is completed, restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Clear RxISR function pointer */
+ huart->RxISR = NULL;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered Rx complete callback*/
+ huart->RxCpltCallback(huart);
+#else
+ /*Call legacy weak Rx complete callback*/
+ HAL_UART_RxCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+ }
+}
+
+/**
+ * @brief RX interrrupt handler for 9 bits data word length .
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_UART_Receive_IT()
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_RxISR_16BIT(UART_HandleTypeDef *huart)
+{
+ uint16_t *tmp;
+ uint16_t uhMask = huart->Mask;
+ uint16_t uhdata;
+
+ /* Check that a Rx process is ongoing */
+ if (huart->RxState == HAL_UART_STATE_BUSY_RX)
+ {
+ uhdata = (uint16_t) READ_REG(huart->Instance->RDR);
+ tmp = (uint16_t *) huart->pRxBuffPtr ;
+ *tmp = (uint16_t)(uhdata & uhMask);
+ huart->pRxBuffPtr += 2U;
+ huart->RxXferCount--;
+
+ if (huart->RxXferCount == 0U)
+ {
+ /* Disable the UART Parity Error Interrupt and RXNE interrupt*/
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+
+ /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
+
+ /* Rx process is completed, restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Clear RxISR function pointer */
+ huart->RxISR = NULL;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered Rx complete callback*/
+ huart->RxCpltCallback(huart);
+#else
+ /*Call legacy weak Rx complete callback*/
+ HAL_UART_RxCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+ }
+}
+
+/**
+ * @brief RX interrrupt handler for 7 or 8 bits data word length and FIFO mode is enabled.
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_UART_Receive_IT()
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_RxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart)
+{
+ uint16_t uhMask = huart->Mask;
+ uint16_t uhdata;
+ uint16_t nb_rx_data;
+ uint16_t rxdatacount;
+
+ /* Check that a Rx process is ongoing */
+ if (huart->RxState == HAL_UART_STATE_BUSY_RX)
+ {
+ for (nb_rx_data = huart->NbRxDataToProcess ; nb_rx_data > 0U ; nb_rx_data--)
+ {
+ uhdata = (uint16_t) READ_REG(huart->Instance->RDR);
+ *huart->pRxBuffPtr = (uint8_t)(uhdata & (uint8_t)uhMask);
+ huart->pRxBuffPtr++;
+ huart->RxXferCount--;
+
+ if (huart->RxXferCount == 0U)
+ {
+ /* Disable the UART Parity Error Interrupt and RXFT interrupt*/
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
+
+ /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) and RX FIFO Threshold interrupt */
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE));
+
+ /* Rx process is completed, restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Clear RxISR function pointer */
+ huart->RxISR = NULL;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered Rx complete callback*/
+ huart->RxCpltCallback(huart);
+#else
+ /*Call legacy weak Rx complete callback*/
+ HAL_UART_RxCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* When remaining number of bytes to receive is less than the RX FIFO
+ threshold, next incoming frames are processed as if FIFO mode was
+ disabled (i.e. one interrupt per received frame).
+ */
+ rxdatacount = huart->RxXferCount;
+ if ((rxdatacount != 0U) && (rxdatacount < huart->NbRxDataToProcess))
+ {
+ /* Disable the UART RXFT interrupt*/
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_RXFTIE);
+
+ /* Update the RxISR function pointer */
+ huart->RxISR = UART_RxISR_8BIT;
+
+ /* Enable the UART Data Register Not Empty interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);
+ }
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+ }
+}
+
+/**
+ * @brief RX interrrupt handler for 9 bits data word length and FIFO mode is enabled.
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_UART_Receive_IT()
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UART_RxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart)
+{
+ uint16_t *tmp;
+ uint16_t uhMask = huart->Mask;
+ uint16_t uhdata;
+ uint16_t nb_rx_data;
+ uint16_t rxdatacount;
+
+ /* Check that a Rx process is ongoing */
+ if (huart->RxState == HAL_UART_STATE_BUSY_RX)
+ {
+ for (nb_rx_data = huart->NbRxDataToProcess ; nb_rx_data > 0U ; nb_rx_data--)
+ {
+ uhdata = (uint16_t) READ_REG(huart->Instance->RDR);
+ tmp = (uint16_t *) huart->pRxBuffPtr ;
+ *tmp = (uint16_t)(uhdata & uhMask);
+ huart->pRxBuffPtr += 2U;
+ huart->RxXferCount--;
+
+ if (huart->RxXferCount == 0U)
+ {
+ /* Disable the UART Parity Error Interrupt and RXFT interrupt*/
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
+
+ /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) and RX FIFO Threshold interrupt */
+ CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE));
+
+ /* Rx process is completed, restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ /* Clear RxISR function pointer */
+ huart->RxISR = NULL;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ /*Call registered Rx complete callback*/
+ huart->RxCpltCallback(huart);
+#else
+ /*Call legacy weak Rx complete callback*/
+ HAL_UART_RxCpltCallback(huart);
+#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* When remaining number of bytes to receive is less than the RX FIFO
+ threshold, next incoming frames are processed as if FIFO mode was
+ disabled (i.e. one interrupt per received frame).
+ */
+ rxdatacount = huart->RxXferCount;
+ if ((rxdatacount != 0U) && (rxdatacount < huart->NbRxDataToProcess))
+ {
+ /* Disable the UART RXFT interrupt*/
+ CLEAR_BIT(huart->Instance->CR3, USART_CR3_RXFTIE);
+
+ /* Update the RxISR function pointer */
+ huart->RxISR = UART_RxISR_16BIT;
+
+ /* Enable the UART Data Register Not Empty interrupt */
+ SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);
+ }
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_UART_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c
new file mode 100644
index 0000000000..949208523e
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c
@@ -0,0 +1,729 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_uart_ex.c
+ * @author MCD Application Team
+ * @brief Extended UART HAL module driver.
+ * This file provides firmware functions to manage the following extended
+ * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART).
+ * + Initialization and de-initialization functions
+ * + Peripheral Control functions
+ *
+ *
+ @verbatim
+ ==============================================================================
+ ##### UART peripheral extended features #####
+ ==============================================================================
+
+ (#) Declare a UART_HandleTypeDef handle structure.
+
+ (#) For the UART RS485 Driver Enable mode, initialize the UART registers
+ by calling the HAL_RS485Ex_Init() API.
+
+ (#) FIFO mode enabling/disabling and RX/TX FIFO threshold programming.
+
+ -@- When UART operates in FIFO mode, FIFO mode must be enabled prior
+ starting RX/TX transfers. Also RX/TX FIFO thresholds must be
+ configured prior starting RX/TX transfers.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup UARTEx UARTEx
+ * @brief UART Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_UART_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup UARTEX_Private_Constants UARTEx Private Constants
+ * @{
+ */
+/* UART RX FIFO depth */
+#define RX_FIFO_DEPTH 8U
+
+/* UART TX FIFO depth */
+#define TX_FIFO_DEPTH 8U
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup UARTEx_Private_Functions UARTEx Private Functions
+ * @{
+ */
+static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection);
+static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup UARTEx_Exported_Functions UARTEx Exported Functions
+ * @{
+ */
+
+/** @defgroup UARTEx_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Extended Initialization and Configuration Functions
+ *
+@verbatim
+===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
+ in asynchronous mode.
+ (+) For the asynchronous mode the parameters below can be configured:
+ (++) Baud Rate
+ (++) Word Length
+ (++) Stop Bit
+ (++) Parity: If the parity is enabled, then the MSB bit of the data written
+ in the data register is transmitted but is changed by the parity bit.
+ (++) Hardware flow control
+ (++) Receiver/transmitter modes
+ (++) Over Sampling Method
+ (++) One-Bit Sampling Method
+ (+) For the asynchronous mode, the following advanced features can be configured as well:
+ (++) TX and/or RX pin level inversion
+ (++) data logical level inversion
+ (++) RX and TX pins swap
+ (++) RX overrun detection disabling
+ (++) DMA disabling on RX error
+ (++) MSB first on communication line
+ (++) auto Baud rate detection
+ [..]
+ The HAL_RS485Ex_Init() API follows the UART RS485 mode configuration
+ procedures (details for the procedures are available in reference manual).
+
+@endverbatim
+
+ Depending on the frame length defined by the M1 and M0 bits (7-bit,
+ 8-bit or 9-bit), the possible UART formats are listed in the
+ following table.
+
+ Table 1. UART frame format.
+ +-----------------------------------------------------------------------+
+ | M1 bit | M0 bit | PCE bit | UART frame |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 0 | | SB | 8 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 0 | | SB | 9 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 0 | | SB | 7 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | |
+ +-----------------------------------------------------------------------+
+
+ * @{
+ */
+
+/**
+ * @brief Initialize the RS485 Driver enable feature according to the specified
+ * parameters in the UART_InitTypeDef and creates the associated handle.
+ * @param huart UART handle.
+ * @param Polarity Select the driver enable polarity.
+ * This parameter can be one of the following values:
+ * @arg @ref UART_DE_POLARITY_HIGH DE signal is active high
+ * @arg @ref UART_DE_POLARITY_LOW DE signal is active low
+ * @param AssertionTime Driver Enable assertion time:
+ * 5-bit value defining the time between the activation of the DE (Driver Enable)
+ * signal and the beginning of the start bit. It is expressed in sample time
+ * units (1/8 or 1/16 bit time, depending on the oversampling rate)
+ * @param DeassertionTime Driver Enable deassertion time:
+ * 5-bit value defining the time between the end of the last stop bit, in a
+ * transmitted message, and the de-activation of the DE (Driver Enable) signal.
+ * It is expressed in sample time units (1/8 or 1/16 bit time, depending on the
+ * oversampling rate).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime,
+ uint32_t DeassertionTime)
+{
+ uint32_t temp;
+
+ /* Check the UART handle allocation */
+ if (huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+ /* Check the Driver Enable UART instance */
+ assert_param(IS_UART_DRIVER_ENABLE_INSTANCE(huart->Instance));
+
+ /* Check the Driver Enable polarity */
+ assert_param(IS_UART_DE_POLARITY(Polarity));
+
+ /* Check the Driver Enable assertion time */
+ assert_param(IS_UART_ASSERTIONTIME(AssertionTime));
+
+ /* Check the Driver Enable deassertion time */
+ assert_param(IS_UART_DEASSERTIONTIME(DeassertionTime));
+
+ if (huart->gState == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
+ UART_InitCallbacksToDefault(huart);
+
+ if (huart->MspInitCallback == NULL)
+ {
+ huart->MspInitCallback = HAL_UART_MspInit;
+ }
+
+ /* Init the low level hardware */
+ huart->MspInitCallback(huart);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX */
+ HAL_UART_MspInit(huart);
+#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
+ }
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* Enable the Driver Enable mode by setting the DEM bit in the CR3 register */
+ SET_BIT(huart->Instance->CR3, USART_CR3_DEM);
+
+ /* Set the Driver Enable polarity */
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_DEP, Polarity);
+
+ /* Set the Driver Enable assertion and deassertion times */
+ temp = (AssertionTime << UART_CR1_DEAT_ADDRESS_LSB_POS);
+ temp |= (DeassertionTime << UART_CR1_DEDT_ADDRESS_LSB_POS);
+ MODIFY_REG(huart->Instance->CR1, (USART_CR1_DEDT | USART_CR1_DEAT), temp);
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup UARTEx_Exported_Functions_Group2 IO operation functions
+ * @brief Extended functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ This subsection provides a set of Wakeup and FIFO mode related callback functions.
+
+ (#) Wakeup from Stop mode Callback:
+ (+) HAL_UARTEx_WakeupCallback()
+
+ (#) TX/RX Fifos Callbacks:
+ (+) HAL_UARTEx_RxFifoFullCallback()
+ (+) HAL_UARTEx_TxFifoEmptyCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief UART wakeup from Stop mode callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UARTEx_WakeupCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief UART RX Fifo full callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UARTEx_RxFifoFullCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief UART TX Fifo empty callback.
+ * @param huart UART handle.
+ * @retval None
+ */
+__weak void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UARTEx_TxFifoEmptyCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup UARTEx_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides the following functions:
+ (+) HAL_MultiProcessorEx_AddressLength_Set() API optionally sets the UART node address
+ detection length to more than 4 bits for multiprocessor address mark wake up.
+ (+) HAL_UARTEx_StopModeWakeUpSourceConfig() API defines the wake-up from stop mode
+ trigger: address match, Start Bit detection or RXNE bit status.
+ (+) HAL_UARTEx_EnableStopMode() API enables the UART to wake up the MCU from stop mode
+ (+) HAL_UARTEx_DisableStopMode() API disables the above functionality
+ (+) HAL_UARTEx_EnableFifoMode() API enables the FIFO mode
+ (+) HAL_UARTEx_DisableFifoMode() API disables the FIFO mode
+ (+) HAL_UARTEx_SetTxFifoThreshold() API sets the TX FIFO threshold
+ (+) HAL_UARTEx_SetRxFifoThreshold() API sets the RX FIFO threshold
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief By default in multiprocessor mode, when the wake up method is set
+ * to address mark, the UART handles only 4-bit long addresses detection;
+ * this API allows to enable longer addresses detection (6-, 7- or 8-bit
+ * long).
+ * @note Addresses detection lengths are: 6-bit address detection in 7-bit data mode,
+ * 7-bit address detection in 8-bit data mode, 8-bit address detection in 9-bit data mode.
+ * @param huart UART handle.
+ * @param AddressLength This parameter can be one of the following values:
+ * @arg @ref UART_ADDRESS_DETECT_4B 4-bit long address
+ * @arg @ref UART_ADDRESS_DETECT_7B 6-, 7- or 8-bit long address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength)
+{
+ /* Check the UART handle allocation */
+ if (huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the address length parameter */
+ assert_param(IS_UART_ADDRESSLENGTH_DETECT(AddressLength));
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the address length */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, AddressLength);
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->gState to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+/**
+ * @brief Set Wakeup from Stop mode interrupt flag selection.
+ * @note It is the application responsibility to enable the interrupt used as
+ * usart_wkup interrupt source before entering low-power mode.
+ * @param huart UART handle.
+ * @param WakeUpSelection Address match, Start Bit detection or RXNE/RXFNE bit status.
+ * This parameter can be one of the following values:
+ * @arg @ref UART_WAKEUP_ON_ADDRESS
+ * @arg @ref UART_WAKEUP_ON_STARTBIT
+ * @arg @ref UART_WAKEUP_ON_READDATA_NONEMPTY
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tickstart;
+
+ /* check the wake-up from stop mode UART instance */
+ assert_param(IS_UART_WAKEUP_FROMSTOP_INSTANCE(huart->Instance));
+ /* check the wake-up selection parameter */
+ assert_param(IS_UART_WAKEUP_SELECTION(WakeUpSelection.WakeUpEvent));
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the wake-up selection scheme */
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_WUS, WakeUpSelection.WakeUpEvent);
+
+ if (WakeUpSelection.WakeUpEvent == UART_WAKEUP_ON_ADDRESS)
+ {
+ UARTEx_Wakeup_AddressConfig(huart, WakeUpSelection);
+ }
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Wait until REACK flag is set */
+ if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ }
+ else
+ {
+ /* Initialize the UART State */
+ huart->gState = HAL_UART_STATE_READY;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return status;
+}
+
+/**
+ * @brief Enable UART Stop Mode.
+ * @note The UART is able to wake up the MCU from Stop 1 mode as long as UART clock is HSI or LSE.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ /* Set UESM bit */
+ SET_BIT(huart->Instance->CR1, USART_CR1_UESM);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable UART Stop Mode.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ /* Clear UESM bit */
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_UESM);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the FIFO mode.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef *huart)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Save actual UART configuration */
+ tmpcr1 = READ_REG(huart->Instance->CR1);
+
+ /* Disable UART */
+ __HAL_UART_DISABLE(huart);
+
+ /* Enable FIFO mode */
+ SET_BIT(tmpcr1, USART_CR1_FIFOEN);
+ huart->FifoMode = UART_FIFOMODE_ENABLE;
+
+ /* Restore UART configuration */
+ WRITE_REG(huart->Instance->CR1, tmpcr1);
+
+ /* Determine the number of data to process during RX/TX ISR execution */
+ UARTEx_SetNbDataToProcess(huart);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the FIFO mode.
+ * @param huart UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef *huart)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Save actual UART configuration */
+ tmpcr1 = READ_REG(huart->Instance->CR1);
+
+ /* Disable UART */
+ __HAL_UART_DISABLE(huart);
+
+ /* Enable FIFO mode */
+ CLEAR_BIT(tmpcr1, USART_CR1_FIFOEN);
+ huart->FifoMode = UART_FIFOMODE_DISABLE;
+
+ /* Restore UART configuration */
+ WRITE_REG(huart->Instance->CR1, tmpcr1);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the TXFIFO threshold.
+ * @param huart UART handle.
+ * @param Threshold TX FIFO threshold value
+ * This parameter can be one of the following values:
+ * @arg @ref UART_TXFIFO_THRESHOLD_1_8
+ * @arg @ref UART_TXFIFO_THRESHOLD_1_4
+ * @arg @ref UART_TXFIFO_THRESHOLD_1_2
+ * @arg @ref UART_TXFIFO_THRESHOLD_3_4
+ * @arg @ref UART_TXFIFO_THRESHOLD_7_8
+ * @arg @ref UART_TXFIFO_THRESHOLD_8_8
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
+ assert_param(IS_UART_TXFIFO_THRESHOLD(Threshold));
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Save actual UART configuration */
+ tmpcr1 = READ_REG(huart->Instance->CR1);
+
+ /* Disable UART */
+ __HAL_UART_DISABLE(huart);
+
+ /* Update TX threshold configuration */
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_TXFTCFG, Threshold);
+
+ /* Determine the number of data to process during RX/TX ISR execution */
+ UARTEx_SetNbDataToProcess(huart);
+
+ /* Restore UART configuration */
+ WRITE_REG(huart->Instance->CR1, tmpcr1);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the RXFIFO threshold.
+ * @param huart UART handle.
+ * @param Threshold RX FIFO threshold value
+ * This parameter can be one of the following values:
+ * @arg @ref UART_RXFIFO_THRESHOLD_1_8
+ * @arg @ref UART_RXFIFO_THRESHOLD_1_4
+ * @arg @ref UART_RXFIFO_THRESHOLD_1_2
+ * @arg @ref UART_RXFIFO_THRESHOLD_3_4
+ * @arg @ref UART_RXFIFO_THRESHOLD_7_8
+ * @arg @ref UART_RXFIFO_THRESHOLD_8_8
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold)
+{
+ uint32_t tmpcr1;
+
+ /* Check the parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
+ assert_param(IS_UART_RXFIFO_THRESHOLD(Threshold));
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->gState = HAL_UART_STATE_BUSY;
+
+ /* Save actual UART configuration */
+ tmpcr1 = READ_REG(huart->Instance->CR1);
+
+ /* Disable UART */
+ __HAL_UART_DISABLE(huart);
+
+ /* Update RX threshold configuration */
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_RXFTCFG, Threshold);
+
+ /* Determine the number of data to process during RX/TX ISR execution */
+ UARTEx_SetNbDataToProcess(huart);
+
+ /* Restore UART configuration */
+ WRITE_REG(huart->Instance->CR1, tmpcr1);
+
+ huart->gState = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup UARTEx_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Initialize the UART wake-up from stop mode parameters when triggered by address detection.
+ * @param huart UART handle.
+ * @param WakeUpSelection UART wake up from stop mode parameters.
+ * @retval None
+ */
+static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
+{
+ assert_param(IS_UART_ADDRESSLENGTH_DETECT(WakeUpSelection.AddressLength));
+
+ /* Set the USART address length */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, WakeUpSelection.AddressLength);
+
+ /* Set the USART address node */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)WakeUpSelection.Address << UART_CR2_ADDRESS_LSB_POS));
+}
+
+/**
+ * @brief Calculate the number of data to process in RX/TX ISR.
+ * @note The RX FIFO depth and the TX FIFO depth is extracted from
+ * the UART configuration registers.
+ * @param huart UART handle.
+ * @retval None
+ */
+static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart)
+{
+ uint8_t rx_fifo_depth;
+ uint8_t tx_fifo_depth;
+ uint8_t rx_fifo_threshold;
+ uint8_t tx_fifo_threshold;
+ uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
+ uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};
+
+ if (huart->FifoMode == UART_FIFOMODE_DISABLE)
+ {
+ huart->NbTxDataToProcess = 1U;
+ huart->NbRxDataToProcess = 1U;
+ }
+ else
+ {
+ rx_fifo_depth = RX_FIFO_DEPTH;
+ tx_fifo_depth = TX_FIFO_DEPTH;
+ rx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos);
+ tx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos);
+ huart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) / (uint16_t)denominator[tx_fifo_threshold];
+ huart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) / (uint16_t)denominator[rx_fifo_threshold];
+ }
+}
+/**
+ * @}
+ */
+
+#endif /* HAL_UART_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_usart.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_usart.c
new file mode 100644
index 0000000000..7157d5943d
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_usart.c
@@ -0,0 +1,3684 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_usart.c
+ * @author MCD Application Team
+ * @brief USART HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Universal Synchronous/Asynchronous Receiver Transmitter
+ * Peripheral (USART).
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Error functions
+ *
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The USART HAL driver can be used as follows:
+
+ (#) Declare a USART_HandleTypeDef handle structure (eg. USART_HandleTypeDef husart).
+ (#) Initialize the USART low level resources by implementing the HAL_USART_MspInit() API:
+ (++) Enable the USARTx interface clock.
+ (++) USART pins configuration:
+ (+++) Enable the clock for the USART GPIOs.
+ (+++) Configure these USART pins as alternate function pull-up.
+ (++) NVIC configuration if you need to use interrupt process (HAL_USART_Transmit_IT(),
+ HAL_USART_Receive_IT() and HAL_USART_TransmitReceive_IT() APIs):
+ (+++) Configure the USARTx interrupt priority.
+ (+++) Enable the NVIC USART IRQ handle.
+ (++) USART interrupts handling:
+ -@@- The specific USART interrupts (Transmission complete interrupt,
+ RXNE interrupt and Error Interrupts) will be managed using the macros
+ __HAL_USART_ENABLE_IT() and __HAL_USART_DISABLE_IT() inside the transmit and receive process.
+ (++) DMA Configuration if you need to use DMA process (HAL_USART_Transmit_DMA()
+ HAL_USART_Receive_DMA() and HAL_USART_TransmitReceive_DMA() APIs):
+ (+++) Declare a DMA handle structure for the Tx/Rx channel.
+ (+++) Enable the DMAx interface clock.
+ (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
+ (+++) Configure the DMA Tx/Rx channel.
+ (+++) Associate the initialized DMA handle to the USART DMA Tx/Rx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
+
+ (#) Program the Baud Rate, Word Length, Stop Bit, Parity, and Mode
+ (Receiver/Transmitter) in the husart handle Init structure.
+
+ (#) Initialize the USART registers by calling the HAL_USART_Init() API:
+ (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
+ by calling the customized HAL_USART_MspInit(&husart) API.
+
+ [..]
+ (@) To configure and enable/disable the USART to wake up the MCU from stop mode, resort to UART API's
+ HAL_UARTEx_StopModeWakeUpSourceConfig(), HAL_UARTEx_EnableStopMode() and
+ HAL_UARTEx_DisableStopMode() in casting the USART handle to UART type UART_HandleTypeDef.
+
+ ##### Callback registration #####
+ ==================================
+
+ [..]
+ The compilation define USE_HAL_USART_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ [..]
+ Use Function @ref HAL_USART_RegisterCallback() to register a user callback.
+ Function @ref HAL_USART_RegisterCallback() allows to register following callbacks:
+ (+) TxHalfCpltCallback : Tx Half Complete Callback.
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxHalfCpltCallback : Rx Half Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) TxRxCpltCallback : Tx Rx Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) AbortCpltCallback : Abort Complete Callback.
+ (+) RxFifoFullCallback : Rx Fifo Full Callback.
+ (+) TxFifoEmptyCallback : Tx Fifo Empty Callback.
+ (+) MspInitCallback : USART MspInit.
+ (+) MspDeInitCallback : USART MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function @ref HAL_USART_UnRegisterCallback() to reset a callback to the default
+ weak (surcharged) function.
+ @ref HAL_USART_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) TxHalfCpltCallback : Tx Half Complete Callback.
+ (+) TxCpltCallback : Tx Complete Callback.
+ (+) RxHalfCpltCallback : Rx Half Complete Callback.
+ (+) RxCpltCallback : Rx Complete Callback.
+ (+) TxRxCpltCallback : Tx Rx Complete Callback.
+ (+) ErrorCallback : Error Callback.
+ (+) AbortCpltCallback : Abort Complete Callback.
+ (+) RxFifoFullCallback : Rx Fifo Full Callback.
+ (+) TxFifoEmptyCallback : Tx Fifo Empty Callback.
+ (+) MspInitCallback : USART MspInit.
+ (+) MspDeInitCallback : USART MspDeInit.
+
+ [..]
+ By default, after the @ref HAL_USART_Init() and when the state is HAL_USART_STATE_RESET
+ all callbacks are set to the corresponding weak (surcharged) functions:
+ examples @ref HAL_USART_TxCpltCallback(), @ref HAL_USART_RxHalfCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are respectively
+ reset to the legacy weak (surcharged) functions in the @ref HAL_USART_Init()
+ and @ref HAL_USART_DeInit() only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the @ref HAL_USART_Init() and @ref HAL_USART_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
+
+ [..]
+ Callbacks can be registered/unregistered in HAL_USART_STATE_READY state only.
+ Exception done MspInit/MspDeInit that can be registered/unregistered
+ in HAL_USART_STATE_READY or HAL_USART_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 @ref HAL_USART_RegisterCallback() before calling @ref HAL_USART_DeInit()
+ or @ref HAL_USART_Init() function.
+
+ [..]
+ When The compilation define USE_HAL_USART_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available
+ and weak (surcharged) callbacks are used.
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup USART USART
+ * @brief HAL USART Synchronous module driver
+ * @{
+ */
+
+#ifdef HAL_USART_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup USART_Private_Constants USART Private Constants
+ * @{
+ */
+#define USART_DUMMY_DATA ((uint16_t) 0xFFFF) /*!< USART transmitted dummy data */
+#define USART_TEACK_REACK_TIMEOUT 1000U /*!< USART TX or RX enable acknowledge time-out value */
+#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \
+ USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8 | \
+ USART_CR1_FIFOEN )) /*!< USART CR1 fields of parameters set by USART_SetConfig API */
+
+#define USART_CR2_FIELDS ((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \
+ USART_CR2_LBCL | USART_CR2_STOP | USART_CR2_SLVEN | \
+ USART_CR2_DIS_NSS)) /*!< USART CR2 fields of parameters set by USART_SetConfig API */
+
+#define USART_CR3_FIELDS ((uint32_t)(USART_CR3_TXFTCFG | USART_CR3_RXFTCFG )) /*!< USART or USART CR3 fields of parameters set by USART_SetConfig API */
+
+#define USART_BRR_MIN 0x10U /* USART BRR minimum authorized value */
+#define USART_BRR_MAX 0xFFFFU /* USART BRR maximum authorized value */
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup USART_Private_Functions
+ * @{
+ */
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+static void USART_EndTransfer(USART_HandleTypeDef *husart);
+static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
+static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
+static void USART_DMAError(DMA_HandleTypeDef *hdma);
+static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma);
+static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
+static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status,
+ uint32_t Tickstart, uint32_t Timeout);
+static HAL_StatusTypeDef USART_SetConfig(USART_HandleTypeDef *husart);
+static HAL_StatusTypeDef USART_CheckIdleState(USART_HandleTypeDef *husart);
+static void USART_TxISR_8BIT(USART_HandleTypeDef *husart);
+static void USART_TxISR_16BIT(USART_HandleTypeDef *husart);
+static void USART_TxISR_8BIT_FIFOEN(USART_HandleTypeDef *husart);
+static void USART_TxISR_16BIT_FIFOEN(USART_HandleTypeDef *husart);
+static void USART_EndTransmit_IT(USART_HandleTypeDef *husart);
+static void USART_RxISR_8BIT(USART_HandleTypeDef *husart);
+static void USART_RxISR_16BIT(USART_HandleTypeDef *husart);
+static void USART_RxISR_8BIT_FIFOEN(USART_HandleTypeDef *husart);
+static void USART_RxISR_16BIT_FIFOEN(USART_HandleTypeDef *husart);
+
+
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup USART_Exported_Functions USART Exported Functions
+ * @{
+ */
+
+/** @defgroup USART_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to initialize the USART
+ in asynchronous and in synchronous modes.
+ (+) For the asynchronous mode only these parameters can be configured:
+ (++) Baud Rate
+ (++) Word Length
+ (++) Stop Bit
+ (++) Parity: If the parity is enabled, then the MSB bit of the data written
+ in the data register is transmitted but is changed by the parity bit.
+ (++) USART polarity
+ (++) USART phase
+ (++) USART LastBit
+ (++) Receiver/transmitter modes
+
+ [..]
+ The HAL_USART_Init() function follows the USART synchronous configuration
+ procedure (details for the procedure are available in reference manual).
+
+@endverbatim
+
+ Depending on the frame length defined by the M1 and M0 bits (7-bit,
+ 8-bit or 9-bit), the possible USART formats are listed in the
+ following table.
+
+ Table 1. USART frame format.
+ +-----------------------------------------------------------------------+
+ | M1 bit | M0 bit | PCE bit | USART frame |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 0 | | SB | 8 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 0 | | SB | 9 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 0 | | SB | 7 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | |
+ +-----------------------------------------------------------------------+
+
+ * @{
+ */
+
+/**
+ * @brief Initialize the USART mode according to the specified
+ * parameters in the USART_InitTypeDef and initialize the associated handle.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart)
+{
+ /* Check the USART handle allocation */
+ if (husart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_USART_INSTANCE(husart->Instance));
+
+ if (husart->State == HAL_USART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ husart->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ USART_InitCallbacksToDefault(husart);
+
+ if (husart->MspInitCallback == NULL)
+ {
+ husart->MspInitCallback = HAL_USART_MspInit;
+ }
+
+ /* Init the low level hardware */
+ husart->MspInitCallback(husart);
+#else
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_USART_MspInit(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+
+ husart->State = HAL_USART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_USART_DISABLE(husart);
+
+ /* Set the Usart Communication parameters */
+ if (USART_SetConfig(husart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ /* In Synchronous mode, the following bits must be kept cleared:
+ - LINEN bit in the USART_CR2 register
+ - HDSEL, SCEN and IREN bits in the USART_CR3 register.
+ */
+ husart->Instance->CR2 &= ~USART_CR2_LINEN;
+ husart->Instance->CR3 &= ~(USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN);
+
+ /* Enable the Peripheral */
+ __HAL_USART_ENABLE(husart);
+
+ /* TEACK and/or REACK to check before moving husart->State to Ready */
+ return (USART_CheckIdleState(husart));
+}
+
+/**
+ * @brief DeInitialize the USART peripheral.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_DeInit(USART_HandleTypeDef *husart)
+{
+ /* Check the USART handle allocation */
+ if (husart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_USART_INSTANCE(husart->Instance));
+
+ husart->State = HAL_USART_STATE_BUSY;
+
+ husart->Instance->CR1 = 0x0U;
+ husart->Instance->CR2 = 0x0U;
+ husart->Instance->CR3 = 0x0U;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ if (husart->MspDeInitCallback == NULL)
+ {
+ husart->MspDeInitCallback = HAL_USART_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ husart->MspDeInitCallback(husart);
+#else
+ /* DeInit the low level hardware */
+ HAL_USART_MspDeInit(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_RESET;
+
+ /* Process Unlock */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the USART MSP.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USART_MspInit(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_USART_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the USART MSP.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_USART_MspDeInit can be implemented in the user file
+ */
+}
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User USART Callback
+ * To be used instead of the weak predefined callback
+ * @param husart usart handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
+ * @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
+ * @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
+ * @arg @ref HAL_USART_RX_FIFO_FULL_CB_ID Rx Fifo Full Callback ID
+ * @arg @ref HAL_USART_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty Callback ID
+ * @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID
+ * @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
++ */
+HAL_StatusTypeDef HAL_USART_RegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID,
+ pUSART_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(husart);
+
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_USART_TX_HALFCOMPLETE_CB_ID :
+ husart->TxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_USART_TX_COMPLETE_CB_ID :
+ husart->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_USART_RX_HALFCOMPLETE_CB_ID :
+ husart->RxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_USART_RX_COMPLETE_CB_ID :
+ husart->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_USART_TX_RX_COMPLETE_CB_ID :
+ husart->TxRxCpltCallback = pCallback;
+ break;
+
+ case HAL_USART_ERROR_CB_ID :
+ husart->ErrorCallback = pCallback;
+ break;
+
+ case HAL_USART_ABORT_COMPLETE_CB_ID :
+ husart->AbortCpltCallback = pCallback;
+ break;
+
+ case HAL_USART_RX_FIFO_FULL_CB_ID :
+ husart->RxFifoFullCallback = pCallback;
+ break;
+
+ case HAL_USART_TX_FIFO_EMPTY_CB_ID :
+ husart->TxFifoEmptyCallback = pCallback;
+ break;
+
+ case HAL_USART_MSPINIT_CB_ID :
+ husart->MspInitCallback = pCallback;
+ break;
+
+ case HAL_USART_MSPDEINIT_CB_ID :
+ husart->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (husart->State == HAL_USART_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_USART_MSPINIT_CB_ID :
+ husart->MspInitCallback = pCallback;
+ break;
+
+ case HAL_USART_MSPDEINIT_CB_ID :
+ husart->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(husart);
+
+ return status;
+}
+
+/**
+ * @brief Unregister an UART Callback
+ * UART callaback is redirected to the weak predefined callback
+ * @param husart uart handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
+ * @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID
+ * @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
+ * @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID
+ * @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
+ * @arg @ref HAL_USART_RX_FIFO_FULL_CB_ID Rx Fifo Full Callback ID
+ * @arg @ref HAL_USART_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty Callback ID
+ * @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID
+ * @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_UnRegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(husart);
+
+ if (HAL_USART_STATE_READY == husart->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_USART_TX_HALFCOMPLETE_CB_ID :
+ husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ break;
+
+ case HAL_USART_TX_COMPLETE_CB_ID :
+ husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ break;
+
+ case HAL_USART_RX_HALFCOMPLETE_CB_ID :
+ husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ break;
+
+ case HAL_USART_RX_COMPLETE_CB_ID :
+ husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ break;
+
+ case HAL_USART_TX_RX_COMPLETE_CB_ID :
+ husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
+ break;
+
+ case HAL_USART_ERROR_CB_ID :
+ husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_USART_ABORT_COMPLETE_CB_ID :
+ husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ break;
+
+ case HAL_USART_RX_FIFO_FULL_CB_ID :
+ husart->RxFifoFullCallback = HAL_USARTEx_RxFifoFullCallback; /* Legacy weak RxFifoFullCallback */
+ break;
+
+ case HAL_USART_TX_FIFO_EMPTY_CB_ID :
+ husart->TxFifoEmptyCallback = HAL_USARTEx_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */
+ break;
+
+ case HAL_USART_MSPINIT_CB_ID :
+ husart->MspInitCallback = HAL_USART_MspInit; /* Legacy weak MspInitCallback */
+ break;
+
+ case HAL_USART_MSPDEINIT_CB_ID :
+ husart->MspDeInitCallback = HAL_USART_MspDeInit; /* Legacy weak MspDeInitCallback */
+ break;
+
+ default :
+ /* Update the error code */
+ husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_USART_STATE_RESET == husart->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_USART_MSPINIT_CB_ID :
+ husart->MspInitCallback = HAL_USART_MspInit;
+ break;
+
+ case HAL_USART_MSPDEINIT_CB_ID :
+ husart->MspDeInitCallback = HAL_USART_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(husart);
+
+ return status;
+}
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Exported_Functions_Group2 IO operation functions
+ * @brief USART Transmit and Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to manage the USART synchronous
+ data transfers.
+
+ [..] The USART supports master mode only: it cannot receive or send data related to an input
+ clock (SCLK is always an output).
+
+ [..]
+
+ (#) There are two modes of transfer:
+ (++) Blocking mode: The communication is performed in polling mode.
+ The HAL status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) No-Blocking mode: The communication is performed using Interrupts
+ or DMA, These API's return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated USART IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+ The HAL_USART_TxCpltCallback(), HAL_USART_RxCpltCallback() and HAL_USART_TxRxCpltCallback() user callbacks
+ will be executed respectively at the end of the transmit or Receive process
+ The HAL_USART_ErrorCallback()user callback will be executed when a communication error is detected
+
+ (#) Blocking mode API's are :
+ (++) HAL_USART_Transmit() in simplex mode
+ (++) HAL_USART_Receive() in full duplex receive only
+ (++) HAL_USART_TransmitReceive() in full duplex mode
+
+ (#) Non-Blocking mode API's with Interrupt are :
+ (++) HAL_USART_Transmit_IT() in simplex mode
+ (++) HAL_USART_Receive_IT() in full duplex receive only
+ (++) HAL_USART_TransmitReceive_IT() in full duplex mode
+ (++) HAL_USART_IRQHandler()
+
+ (#) No-Blocking mode API's with DMA are :
+ (++) HAL_USART_Transmit_DMA() in simplex mode
+ (++) HAL_USART_Receive_DMA() in full duplex receive only
+ (++) HAL_USART_TransmitReceive_DMA() in full duplex mode
+ (++) HAL_USART_DMAPause()
+ (++) HAL_USART_DMAResume()
+ (++) HAL_USART_DMAStop()
+
+ (#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode:
+ (++) HAL_USART_TxCpltCallback()
+ (++) HAL_USART_RxCpltCallback()
+ (++) HAL_USART_TxHalfCpltCallback()
+ (++) HAL_USART_RxHalfCpltCallback()
+ (++) HAL_USART_ErrorCallback()
+ (++) HAL_USART_TxRxCpltCallback()
+
+ (#) Non-Blocking mode transfers could be aborted using Abort API's :
+ (++) HAL_USART_Abort()
+ (++) HAL_USART_Abort_IT()
+
+ (#) For Abort services based on interrupts (HAL_USART_Abort_IT), a Abort Complete Callbacks is provided:
+ (++) HAL_USART_AbortCpltCallback()
+
+ (#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
+ Errors are handled as follows :
+ (++) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
+ to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
+ Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
+ and HAL_USART_ErrorCallback() user callback is executed. Transfer is kept ongoing on USART side.
+ If user wants to abort it, Abort services should be called by user.
+ (++) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
+ This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
+ Error code is set to allow user to identify error type, and HAL_USART_ErrorCallback() user callback is executed.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Simplex send an amount of data in blocking mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 provided through pTxData.
+ * @param husart USART handle.
+ * @param pTxData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be sent.
+ * @param Timeout Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, uint8_t *pTxData, uint16_t Size, uint32_t Timeout)
+{
+ uint8_t *ptxdata8bits;
+ uint16_t *ptxdata16bits;
+ uint32_t tickstart;
+
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ if ((pTxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_BUSY_TX;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ husart->TxXferSize = Size;
+ husart->TxXferCount = Size;
+
+ /* In case of 9bits/No Parity transfer, pTxData needs to be handled as a uint16_t pointer */
+ if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
+ {
+ ptxdata8bits = NULL;
+ ptxdata16bits = (uint16_t *) pTxData;
+ }
+ else
+ {
+ ptxdata8bits = pTxData;
+ ptxdata16bits = NULL;
+ }
+
+ /* Check the remaining data to be sent */
+ while (husart->TxXferCount > 0U)
+ {
+ if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ if (ptxdata8bits == NULL)
+ {
+ husart->Instance->TDR = (uint16_t)(*ptxdata16bits & 0x01FFU);
+ ptxdata16bits++;
+ }
+ else
+ {
+ husart->Instance->TDR = (uint8_t)(*ptxdata8bits & 0xFFU);
+ ptxdata8bits++;
+ }
+
+ husart->TxXferCount--;
+ }
+
+ if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear Transmission Complete Flag */
+ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_TCF);
+
+ /* Clear overrun flag and discard the received data */
+ __HAL_USART_CLEAR_OREFLAG(husart);
+ __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST);
+ __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST);
+
+ /* At end of Tx process, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @note To receive synchronous data, dummy data are simultaneously transmitted.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 available through pRxData.
+ * @param husart USART handle.
+ * @param pRxData Pointer to data buffer (u8 or u16 data elements).
+ * @param Size Amount of data elements (u8 or u16) to be received.
+ * @param Timeout Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
+{
+ uint8_t *prxdata8bits;
+ uint16_t *prxdata16bits;
+ uint16_t uhMask;
+ uint32_t tickstart;
+
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ if ((pRxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_BUSY_RX;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ husart->RxXferSize = Size;
+ husart->RxXferCount = Size;
+
+ /* Computation of USART mask to apply to RDR register */
+ USART_MASK_COMPUTATION(husart);
+ uhMask = husart->Mask;
+
+ /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
+ if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
+ {
+ prxdata8bits = NULL;
+ prxdata16bits = (uint16_t *) pRxData;
+ }
+ else
+ {
+ prxdata8bits = pRxData;
+ prxdata16bits = NULL;
+ }
+
+ /* as long as data have to be received */
+ while (husart->RxXferCount > 0U)
+ {
+ if (husart->SlaveMode == USART_SLAVEMODE_DISABLE)
+ {
+ /* Wait until TXE flag is set to send dummy byte in order to generate the
+ * clock for the slave to send data.
+ * Whatever the frame length (7, 8 or 9-bit long), the same dummy value
+ * can be written for all the cases. */
+ if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x0FF);
+ }
+
+ /* Wait for RXNE Flag */
+ if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if (prxdata8bits == NULL)
+ {
+ *prxdata16bits = (uint16_t)(husart->Instance->RDR & uhMask);
+ prxdata16bits++;
+ }
+ else
+ {
+ *prxdata8bits = (uint8_t)(husart->Instance->RDR & (uint8_t)(uhMask & 0xFFU));
+ prxdata8bits++;
+ }
+
+ husart->RxXferCount--;
+
+ }
+
+ /* Clear SPI slave underrun flag and discard transmit data */
+ if (husart->SlaveMode == USART_SLAVEMODE_ENABLE)
+ {
+ __HAL_USART_CLEAR_UDRFLAG(husart);
+ __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* At end of Rx process, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Full-Duplex Send and Receive an amount of data in blocking mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number
+ * of u16 available through pTxData and through pRxData.
+ * @param husart USART handle.
+ * @param pTxData pointer to TX data buffer (u8 or u16 data elements).
+ * @param pRxData pointer to RX data buffer (u8 or u16 data elements).
+ * @param Size amount of data elements (u8 or u16) to be sent (same amount to be received).
+ * @param Timeout Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, uint8_t *pTxData, uint8_t *pRxData,
+ uint16_t Size, uint32_t Timeout)
+{
+ uint8_t *prxdata8bits;
+ uint16_t *prxdata16bits;
+ uint8_t *ptxdata8bits;
+ uint16_t *ptxdata16bits;
+ uint16_t uhMask;
+ uint16_t rxdatacount;
+ uint32_t tickstart;
+
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_BUSY_RX;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ husart->RxXferSize = Size;
+ husart->TxXferSize = Size;
+ husart->TxXferCount = Size;
+ husart->RxXferCount = Size;
+
+ /* Computation of USART mask to apply to RDR register */
+ USART_MASK_COMPUTATION(husart);
+ uhMask = husart->Mask;
+
+ /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
+ if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
+ {
+ prxdata8bits = NULL;
+ ptxdata8bits = NULL;
+ ptxdata16bits = (uint16_t *) pTxData;
+ prxdata16bits = (uint16_t *) pRxData;
+ }
+ else
+ {
+ prxdata8bits = pRxData;
+ ptxdata8bits = pTxData;
+ ptxdata16bits = NULL;
+ prxdata16bits = NULL;
+ }
+
+ if ((husart->TxXferCount == 0x01U) || (husart->SlaveMode == USART_SLAVEMODE_ENABLE))
+ {
+ /* Wait until TXE flag is set to send data */
+ if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ if (ptxdata8bits == NULL)
+ {
+ husart->Instance->TDR = (uint16_t)(*ptxdata16bits & uhMask);
+ ptxdata16bits++;
+ }
+ else
+ {
+ husart->Instance->TDR = (uint8_t)(*ptxdata8bits & (uint8_t)(uhMask & 0xFFU));
+ ptxdata8bits++;
+ }
+
+ husart->TxXferCount--;
+ }
+
+ /* Check the remain data to be sent */
+ /* rxdatacount is a temporary variable for MISRAC2012-Rule-13.5 */
+ rxdatacount = husart->RxXferCount;
+ while ((husart->TxXferCount > 0U) || (rxdatacount > 0U))
+ {
+ if (husart->TxXferCount > 0U)
+ {
+ /* Wait until TXE flag is set to send data */
+ if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ if (ptxdata8bits == NULL)
+ {
+ husart->Instance->TDR = (uint16_t)(*ptxdata16bits & uhMask);
+ ptxdata16bits++;
+ }
+ else
+ {
+ husart->Instance->TDR = (uint8_t)(*ptxdata8bits & (uint8_t)(uhMask & 0xFFU));
+ ptxdata8bits++;
+ }
+
+ husart->TxXferCount--;
+ }
+
+ if (husart->RxXferCount > 0U)
+ {
+ /* Wait for RXNE Flag */
+ if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if (prxdata8bits == NULL)
+ {
+ *prxdata16bits = (uint16_t)(husart->Instance->RDR & uhMask);
+ prxdata16bits++;
+ }
+ else
+ {
+ *prxdata8bits = (uint8_t)(husart->Instance->RDR & (uint8_t)(uhMask & 0xFFU));
+ prxdata8bits++;
+ }
+
+ husart->RxXferCount--;
+ }
+ rxdatacount = husart->RxXferCount;
+ }
+
+ /* At end of TxRx process, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in interrupt mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 provided through pTxData.
+ * @param husart USART handle.
+ * @param pTxData pointer to data buffer (u8 or u16 data elements).
+ * @param Size amount of data elements (u8 or u16) to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, uint8_t *pTxData, uint16_t Size)
+{
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ if ((pTxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->pTxBuffPtr = pTxData;
+ husart->TxXferSize = Size;
+ husart->TxXferCount = Size;
+ husart->TxISR = NULL;
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_BUSY_TX;
+
+ /* The USART Error Interrupts: (Frame error, noise error, overrun error)
+ are not managed by the USART Transmit Process to avoid the overrun interrupt
+ when the usart mode is configured for transmit and receive "USART_MODE_TX_RX"
+ to benefit for the frame error and noise interrupts the usart mode should be
+ configured only for transmit "USART_MODE_TX" */
+
+ /* Configure Tx interrupt processing */
+ if (husart->FifoMode == USART_FIFOMODE_ENABLE)
+ {
+ /* Set the Tx ISR function pointer according to the data word length */
+ if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
+ {
+ husart->TxISR = USART_TxISR_16BIT_FIFOEN;
+ }
+ else
+ {
+ husart->TxISR = USART_TxISR_8BIT_FIFOEN;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Enable the TX FIFO threshold interrupt */
+ __HAL_USART_ENABLE_IT(husart, USART_IT_TXFT);
+ }
+ else
+ {
+ /* Set the Tx ISR function pointer according to the data word length */
+ if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
+ {
+ husart->TxISR = USART_TxISR_16BIT;
+ }
+ else
+ {
+ husart->TxISR = USART_TxISR_8BIT;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Enable the USART Transmit Data Register Empty Interrupt */
+ __HAL_USART_ENABLE_IT(husart, USART_IT_TXE);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in interrupt mode.
+ * @note To receive synchronous data, dummy data are simultaneously transmitted.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 available through pRxData.
+ * @param husart USART handle.
+ * @param pRxData pointer to data buffer (u8 or u16 data elements).
+ * @param Size amount of data elements (u8 or u16) to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_Receive_IT(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size)
+{
+ uint16_t nb_dummy_data;
+
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ if ((pRxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->pRxBuffPtr = pRxData;
+ husart->RxXferSize = Size;
+ husart->RxXferCount = Size;
+ husart->RxISR = NULL;
+
+ USART_MASK_COMPUTATION(husart);
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_BUSY_RX;
+
+ /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Configure Rx interrupt processing */
+ if ((husart->FifoMode == USART_FIFOMODE_ENABLE) && (Size >= husart->NbRxDataToProcess))
+ {
+ /* Set the Rx ISR function pointer according to the data word length */
+ if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
+ {
+ husart->RxISR = USART_RxISR_16BIT_FIFOEN;
+ }
+ else
+ {
+ husart->RxISR = USART_RxISR_8BIT_FIFOEN;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Enable the USART Parity Error interrupt and RX FIFO Threshold interrupt */
+ SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
+ SET_BIT(husart->Instance->CR3, USART_CR3_RXFTIE);
+ }
+ else
+ {
+ /* Set the Rx ISR function pointer according to the data word length */
+ if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
+ {
+ husart->RxISR = USART_RxISR_16BIT;
+ }
+ else
+ {
+ husart->RxISR = USART_RxISR_8BIT;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Enable the USART Parity Error and Data Register not empty Interrupts */
+ SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE);
+ }
+
+ if (husart->SlaveMode == USART_SLAVEMODE_DISABLE)
+ {
+ /* Send dummy data in order to generate the clock for the Slave to send the next data.
+ When FIFO mode is disabled only one data must be transferred.
+ When FIFO mode is enabled data must be transmitted until the RX FIFO reaches its threshold.
+ */
+ if ((husart->FifoMode == USART_FIFOMODE_ENABLE) && (Size >= husart->NbRxDataToProcess))
+ {
+ for (nb_dummy_data = husart->NbRxDataToProcess ; nb_dummy_data > 0U ; nb_dummy_data--)
+ {
+ husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF);
+ }
+ }
+ else
+ {
+ husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF);
+ }
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Full-Duplex Send and Receive an amount of data in interrupt mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number
+ * of u16 available through pTxData and through pRxData.
+ * @param husart USART handle.
+ * @param pTxData pointer to TX data buffer (u8 or u16 data elements).
+ * @param pRxData pointer to RX data buffer (u8 or u16 data elements).
+ * @param Size amount of data elements (u8 or u16) to be sent (same amount to be received).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, uint8_t *pTxData, uint8_t *pRxData,
+ uint16_t Size)
+{
+
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->pRxBuffPtr = pRxData;
+ husart->RxXferSize = Size;
+ husart->RxXferCount = Size;
+ husart->pTxBuffPtr = pTxData;
+ husart->TxXferSize = Size;
+ husart->TxXferCount = Size;
+
+ /* Computation of USART mask to apply to RDR register */
+ USART_MASK_COMPUTATION(husart);
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_BUSY_TX_RX;
+
+ /* Configure TxRx interrupt processing */
+ if ((husart->FifoMode == USART_FIFOMODE_ENABLE) && (Size >= husart->NbRxDataToProcess))
+ {
+ /* Set the Rx ISR function pointer according to the data word length */
+ if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
+ {
+ husart->TxISR = USART_TxISR_16BIT_FIFOEN;
+ husart->RxISR = USART_RxISR_16BIT_FIFOEN;
+ }
+ else
+ {
+ husart->TxISR = USART_TxISR_8BIT_FIFOEN;
+ husart->RxISR = USART_RxISR_8BIT_FIFOEN;
+ }
+
+ /* Process Locked */
+ __HAL_UNLOCK(husart);
+
+ /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the USART Parity Error interrupt */
+ SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
+
+ /* Enable the TX and RX FIFO Threshold interrupts */
+ SET_BIT(husart->Instance->CR3, (USART_CR3_TXFTIE | USART_CR3_RXFTIE));
+ }
+ else
+ {
+ if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
+ {
+ husart->TxISR = USART_TxISR_16BIT;
+ husart->RxISR = USART_RxISR_16BIT;
+ }
+ else
+ {
+ husart->TxISR = USART_TxISR_8BIT;
+ husart->RxISR = USART_RxISR_8BIT;
+ }
+
+ /* Process Locked */
+ __HAL_UNLOCK(husart);
+
+ /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the USART Parity Error and USART Data Register not empty Interrupts */
+ SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE);
+
+ /* Enable the USART Transmit Data Register Empty Interrupt */
+ SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in DMA mode.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 provided through pTxData.
+ * @param husart USART handle.
+ * @param pTxData pointer to data buffer (u8 or u16 data elements).
+ * @param Size amount of data elements (u8 or u16) to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_Transmit_DMA(USART_HandleTypeDef *husart, uint8_t *pTxData, uint16_t Size)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t *tmp;
+
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ if ((pTxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->pTxBuffPtr = pTxData;
+ husart->TxXferSize = Size;
+ husart->TxXferCount = Size;
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_BUSY_TX;
+
+ if (husart->hdmatx != NULL)
+ {
+ /* Set the USART DMA transfer complete callback */
+ husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt;
+
+ /* Set the USART DMA Half transfer complete callback */
+ husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt;
+
+ /* Set the DMA error callback */
+ husart->hdmatx->XferErrorCallback = USART_DMAError;
+
+ /* Enable the USART transmit DMA channel */
+ tmp = (uint32_t *)&pTxData;
+ status = HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->TDR, Size);
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Clear the TC flag in the ICR register */
+ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_TCF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Enable the DMA transfer for transmit request by setting the DMAT bit
+ in the USART CR3 register */
+ SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Set error code to DMA */
+ husart->ErrorCode = HAL_USART_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Restore husart->State to ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in DMA mode.
+ * @note When the USART parity is enabled (PCE = 1), the received data contain
+ * the parity bit (MSB position).
+ * @note The USART DMA transmit channel must be configured in order to generate the clock for the slave.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of u16. In this case, Size must indicate the number
+ * of u16 available through pRxData.
+ * @param husart USART handle.
+ * @param pRxData pointer to data buffer (u8 or u16 data elements).
+ * @param Size amount of data elements (u8 or u16) to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_Receive_DMA(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t *tmp = (uint32_t *)&pRxData;
+
+ /* Check that a Rx process is not already ongoing */
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ if ((pRxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->pRxBuffPtr = pRxData;
+ husart->RxXferSize = Size;
+ husart->pTxBuffPtr = pRxData;
+ husart->TxXferSize = Size;
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_BUSY_RX;
+
+ if (husart->hdmarx != NULL)
+ {
+ /* Set the USART DMA Rx transfer complete callback */
+ husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt;
+
+ /* Set the USART DMA Half transfer complete callback */
+ husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt;
+
+ /* Set the USART DMA Rx transfer error callback */
+ husart->hdmarx->XferErrorCallback = USART_DMAError;
+
+ /* Enable the USART receive DMA channel */
+ status = HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->RDR, *(uint32_t *)tmp, Size);
+ }
+
+ if ((status == HAL_OK) &&
+ (husart->SlaveMode == USART_SLAVEMODE_DISABLE))
+ {
+ /* Enable the USART transmit DMA channel: the transmit channel is used in order
+ to generate in the non-blocking mode the clock to the slave device,
+ this mode isn't a simplex receive mode but a full-duplex receive mode */
+
+ /* Set the USART DMA Tx Complete and Error callback to Null */
+ if (husart->hdmatx != NULL)
+ {
+ husart->hdmatx->XferErrorCallback = NULL;
+ husart->hdmatx->XferHalfCpltCallback = NULL;
+ husart->hdmatx->XferCpltCallback = NULL;
+ status = HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->TDR, Size);
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Enable the USART Parity Error Interrupt */
+ SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
+
+ /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the DMA transfer for the receiver request by setting the DMAR bit
+ in the USART CR3 register */
+ SET_BIT(husart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Enable the DMA transfer for transmit request by setting the DMAT bit
+ in the USART CR3 register */
+ SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ if (husart->hdmarx != NULL)
+ {
+ status = HAL_DMA_Abort(husart->hdmarx);
+ }
+
+ /* No need to check on error code */
+ UNUSED(status);
+
+ /* Set error code to DMA */
+ husart->ErrorCode = HAL_USART_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Restore husart->State to ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Full-Duplex Transmit Receive an amount of data in non-blocking mode.
+ * @note When the USART parity is enabled (PCE = 1) the data received contain the parity bit.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number
+ * of u16 available through pTxData and through pRxData.
+ * @param husart USART handle.
+ * @param pTxData pointer to TX data buffer (u8 or u16 data elements).
+ * @param pRxData pointer to RX data buffer (u8 or u16 data elements).
+ * @param Size amount of data elements (u8 or u16) to be received/sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, uint8_t *pTxData, uint8_t *pRxData,
+ uint16_t Size)
+{
+ HAL_StatusTypeDef status;
+ uint32_t *tmp;
+
+ if (husart->State == HAL_USART_STATE_READY)
+ {
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->pRxBuffPtr = pRxData;
+ husart->RxXferSize = Size;
+ husart->pTxBuffPtr = pTxData;
+ husart->TxXferSize = Size;
+
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ husart->State = HAL_USART_STATE_BUSY_TX_RX;
+
+ if ((husart->hdmarx != NULL) && (husart->hdmatx != NULL))
+ {
+ /* Set the USART DMA Rx transfer complete callback */
+ husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt;
+
+ /* Set the USART DMA Half transfer complete callback */
+ husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt;
+
+ /* Set the USART DMA Tx transfer complete callback */
+ husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt;
+
+ /* Set the USART DMA Half transfer complete callback */
+ husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt;
+
+ /* Set the USART DMA Tx transfer error callback */
+ husart->hdmatx->XferErrorCallback = USART_DMAError;
+
+ /* Set the USART DMA Rx transfer error callback */
+ husart->hdmarx->XferErrorCallback = USART_DMAError;
+
+ /* Enable the USART receive DMA channel */
+ tmp = (uint32_t *)&pRxData;
+ status = HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->RDR, *(uint32_t *)tmp, Size);
+
+ /* Enable the USART transmit DMA channel */
+ if (status == HAL_OK)
+ {
+ tmp = (uint32_t *)&pTxData;
+ status = HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->TDR, Size);
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Enable the USART Parity Error Interrupt */
+ SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
+
+ /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
+ SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Clear the TC flag in the ICR register */
+ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_TCF);
+
+ /* Enable the DMA transfer for the receiver request by setting the DMAR bit
+ in the USART CR3 register */
+ SET_BIT(husart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Enable the DMA transfer for transmit request by setting the DMAT bit
+ in the USART CR3 register */
+ SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ if (husart->hdmarx != NULL)
+ {
+ status = HAL_DMA_Abort(husart->hdmarx);
+ }
+
+ /* No need to check on error code */
+ UNUSED(status);
+
+ /* Set error code to DMA */
+ husart->ErrorCode = HAL_USART_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ /* Restore husart->State to ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Pause the DMA Transfer.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_DMAPause(USART_HandleTypeDef *husart)
+{
+ const HAL_USART_StateTypeDef state = husart->State;
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ if ((HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) &&
+ (state == HAL_USART_STATE_BUSY_TX))
+ {
+ /* Disable the USART DMA Tx request */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+ }
+ else if ((state == HAL_USART_STATE_BUSY_RX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
+ {
+ /* Disable the USART DMA Tx request */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+ }
+ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
+ {
+ /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the USART DMA Rx request */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the DMA Transfer.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_DMAResume(USART_HandleTypeDef *husart)
+{
+ const HAL_USART_StateTypeDef state = husart->State;
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ if (state == HAL_USART_STATE_BUSY_TX)
+ {
+ /* Enable the USART DMA Tx request */
+ SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+ }
+ else if ((state == HAL_USART_STATE_BUSY_RX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ /* Clear the Overrun flag before resuming the Rx transfer*/
+ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_OREF);
+
+ /* Reenable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
+ SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Enable the USART DMA Rx request before the DMA Tx request */
+ SET_BIT(husart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Enable the USART DMA Tx request */
+ SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the DMA Transfer.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_DMAStop(USART_HandleTypeDef *husart)
+{
+ /* The Lock is not implemented on this API to allow the user application
+ to call the HAL USART API under callbacks HAL_USART_TxCpltCallback() / HAL_USART_RxCpltCallback() /
+ HAL_USART_TxHalfCpltCallback / HAL_USART_RxHalfCpltCallback:
+ indeed, when HAL_DMA_Abort() API is called, the DMA TX/RX Transfer or Half Transfer complete
+ interrupt is generated if the DMA transfer interruption occurs at the middle or at the end of
+ the stream and the corresponding call back is executed. */
+
+ /* Disable the USART Tx/Rx DMA requests */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the USART DMA tx channel */
+ if (husart->hdmatx != NULL)
+ {
+ if (HAL_DMA_Abort(husart->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(husart->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ husart->ErrorCode = HAL_USART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ /* Abort the USART DMA rx channel */
+ if (husart->hdmarx != NULL)
+ {
+ if (HAL_DMA_Abort(husart->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(husart->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ husart->ErrorCode = HAL_USART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ USART_EndTransfer(husart);
+ husart->State = HAL_USART_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing transfers (blocking mode).
+ * @param husart USART handle.
+ * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable USART Interrupts (Tx and Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_Abort(USART_HandleTypeDef *husart)
+{
+ /* Disable TXEIE, TCIE, RXNE, RXFT, TXFT, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE |
+ USART_CR1_TCIE));
+ CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE));
+
+ /* Disable the USART DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
+ {
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the USART DMA Tx channel : use blocking DMA Abort API (no callback) */
+ if (husart->hdmatx != NULL)
+ {
+ /* Set the USART DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ husart->hdmatx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(husart->hdmatx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(husart->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ husart->ErrorCode = HAL_USART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Disable the USART DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the USART DMA Rx channel : use blocking DMA Abort API (no callback) */
+ if (husart->hdmarx != NULL)
+ {
+ /* Set the USART DMA Abort callback to Null.
+ No call back execution at end of DMA abort procedure */
+ husart->hdmarx->XferAbortCallback = NULL;
+
+ if (HAL_DMA_Abort(husart->hdmarx) != HAL_OK)
+ {
+ if (HAL_DMA_GetError(husart->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
+ {
+ /* Set error code to DMA */
+ husart->ErrorCode = HAL_USART_ERROR_DMA;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Reset Tx and Rx transfer counters */
+ husart->TxXferCount = 0U;
+ husart->RxXferCount = 0U;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_OREF | USART_CLEAR_NEF | USART_CLEAR_PEF | USART_CLEAR_FEF);
+
+ /* Flush the whole TX FIFO (if needed) */
+ if (husart->FifoMode == USART_FIFOMODE_ENABLE)
+ {
+ __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Discard the received data */
+ __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST);
+
+ /* Restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Reset Handle ErrorCode to No Error */
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing transfers (Interrupt mode).
+ * @param husart USART handle.
+ * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable USART Interrupts (Tx and Rx)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USART_Abort_IT(USART_HandleTypeDef *husart)
+{
+ uint32_t abortcplt = 1U;
+
+ /* Disable TXEIE, TCIE, RXNE, RXFT, TXFT, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE |
+ USART_CR1_TCIE));
+ CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE));
+
+ /* If DMA Tx and/or DMA Rx Handles are associated to USART Handle, DMA Abort complete callbacks should be initialised
+ before any call to DMA Abort functions */
+ /* DMA Tx Handle is valid */
+ if (husart->hdmatx != NULL)
+ {
+ /* Set DMA Abort Complete callback if USART DMA Tx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
+ {
+ husart->hdmatx->XferAbortCallback = USART_DMATxAbortCallback;
+ }
+ else
+ {
+ husart->hdmatx->XferAbortCallback = NULL;
+ }
+ }
+ /* DMA Rx Handle is valid */
+ if (husart->hdmarx != NULL)
+ {
+ /* Set DMA Abort Complete callback if USART DMA Rx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
+ {
+ husart->hdmarx->XferAbortCallback = USART_DMARxAbortCallback;
+ }
+ else
+ {
+ husart->hdmarx->XferAbortCallback = NULL;
+ }
+ }
+
+ /* Disable the USART DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
+ {
+ /* Disable DMA Tx at USART level */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+
+ /* Abort the USART DMA Tx channel : use non blocking DMA Abort API (callback) */
+ if (husart->hdmatx != NULL)
+ {
+ /* USART Tx DMA Abort callback has already been initialised :
+ will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(husart->hdmatx) != HAL_OK)
+ {
+ husart->hdmatx->XferAbortCallback = NULL;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+
+ /* Disable the USART DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
+
+ /* Abort the USART DMA Rx channel : use non blocking DMA Abort API (callback) */
+ if (husart->hdmarx != NULL)
+ {
+ /* USART Rx DMA Abort callback has already been initialised :
+ will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK)
+ {
+ husart->hdmarx->XferAbortCallback = NULL;
+ abortcplt = 1U;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+
+ /* if no DMA abort complete callback execution is required => call user Abort Complete callback */
+ if (abortcplt == 1U)
+ {
+ /* Reset Tx and Rx transfer counters */
+ husart->TxXferCount = 0U;
+ husart->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_OREF | USART_CLEAR_NEF | USART_CLEAR_PEF | USART_CLEAR_FEF);
+
+ /* Flush the whole TX FIFO (if needed) */
+ if (husart->FifoMode == USART_FIFOMODE_ENABLE)
+ {
+ __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Discard the received data */
+ __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST);
+
+ /* Restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Complete Callback */
+ husart->AbortCpltCallback(husart);
+#else
+ /* Call legacy weak Abort Complete Callback */
+ HAL_USART_AbortCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle USART interrupt request.
+ * @param husart USART handle.
+ * @retval None
+ */
+void HAL_USART_IRQHandler(USART_HandleTypeDef *husart)
+{
+ uint32_t isrflags = READ_REG(husart->Instance->ISR);
+ uint32_t cr1its = READ_REG(husart->Instance->CR1);
+ uint32_t cr3its = READ_REG(husart->Instance->CR3);
+
+ uint32_t errorflags;
+ uint32_t errorcode;
+
+ /* If no error occurs */
+ errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE | USART_ISR_RTOF | USART_ISR_UDR));
+ if (errorflags == 0U)
+ {
+ /* USART in mode Receiver ---------------------------------------------------*/
+ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
+ && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
+ || ((cr3its & USART_CR3_RXFTIE) != 0U)))
+ {
+ if (husart->RxISR != NULL)
+ {
+ husart->RxISR(husart);
+ }
+ return;
+ }
+ }
+
+ /* If some errors occur */
+ if ((errorflags != 0U)
+ && (((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != 0U)
+ || ((cr1its & (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)) != 0U)))
+ {
+ /* USART parity error interrupt occurred -------------------------------------*/
+ if (((isrflags & USART_ISR_PE) != 0U) && ((cr1its & USART_CR1_PEIE) != 0U))
+ {
+ __HAL_USART_CLEAR_IT(husart, USART_CLEAR_PEF);
+
+ husart->ErrorCode |= HAL_USART_ERROR_PE;
+ }
+
+ /* USART frame error interrupt occurred --------------------------------------*/
+ if (((isrflags & USART_ISR_FE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
+ {
+ __HAL_USART_CLEAR_IT(husart, USART_CLEAR_FEF);
+
+ husart->ErrorCode |= HAL_USART_ERROR_FE;
+ }
+
+ /* USART noise error interrupt occurred --------------------------------------*/
+ if (((isrflags & USART_ISR_NE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
+ {
+ __HAL_USART_CLEAR_IT(husart, USART_CLEAR_NEF);
+
+ husart->ErrorCode |= HAL_USART_ERROR_NE;
+ }
+
+ /* USART Over-Run interrupt occurred -----------------------------------------*/
+ if (((isrflags & USART_ISR_ORE) != 0U)
+ && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) ||
+ ((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != 0U)))
+ {
+ __HAL_USART_CLEAR_IT(husart, USART_CLEAR_OREF);
+
+ husart->ErrorCode |= HAL_USART_ERROR_ORE;
+ }
+
+ /* USART Receiver Timeout interrupt occurred ---------------------------------*/
+ if (((isrflags & USART_ISR_RTOF) != 0U) && ((cr1its & USART_CR1_RTOIE) != 0U))
+ {
+ __HAL_UART_CLEAR_FLAG(husart, UART_CLEAR_RTOF);
+
+ husart->ErrorCode |= HAL_USART_ERROR_RTO;
+ }
+
+ /* USART SPI slave underrun error interrupt occurred -------------------------*/
+ if (((isrflags & USART_ISR_UDR) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
+ {
+ /* Ignore SPI slave underrun errors when reception is going on */
+ if (husart->State == HAL_USART_STATE_BUSY_RX)
+ {
+ __HAL_USART_CLEAR_UDRFLAG(husart);
+ return;
+ }
+ else
+ {
+ __HAL_USART_CLEAR_UDRFLAG(husart);
+ husart->ErrorCode |= HAL_USART_ERROR_UDR;
+ }
+ }
+
+ /* Call USART Error Call back function if need be --------------------------*/
+ if (husart->ErrorCode != HAL_USART_ERROR_NONE)
+ {
+ /* USART in mode Receiver ---------------------------------------------------*/
+ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
+ && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
+ || ((cr3its & USART_CR3_RXFTIE) != 0U)))
+ {
+ if (husart->RxISR != NULL)
+ {
+ husart->RxISR(husart);
+ }
+ }
+
+ /* If Overrun error occurs, or if any error occurs in DMA mode reception,
+ consider error as blocking */
+ errorcode = husart->ErrorCode & HAL_USART_ERROR_ORE;
+ if ((HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR)) ||
+ (errorcode != 0U))
+ {
+ /* Blocking error : transfer is aborted
+ Set the USART state ready to be able to start again the process,
+ Disable Interrupts, and disable DMA requests, if ongoing */
+ USART_EndTransfer(husart);
+
+ /* Disable the USART DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
+ {
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR | USART_CR3_DMAR);
+
+ /* Abort the USART DMA Tx channel */
+ if (husart->hdmatx != NULL)
+ {
+ /* Set the USART Tx DMA Abort callback to NULL : no callback
+ executed at end of DMA abort procedure */
+ husart->hdmatx->XferAbortCallback = NULL;
+
+ /* Abort DMA TX */
+ (void)HAL_DMA_Abort_IT(husart->hdmatx);
+ }
+
+ /* Abort the USART DMA Rx channel */
+ if (husart->hdmarx != NULL)
+ {
+ /* Set the USART Rx DMA Abort callback :
+ will lead to call HAL_USART_ErrorCallback() at end of DMA abort procedure */
+ husart->hdmarx->XferAbortCallback = USART_DMAAbortOnError;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK)
+ {
+ /* Call Directly husart->hdmarx->XferAbortCallback function in case of error */
+ husart->hdmarx->XferAbortCallback(husart->hdmarx);
+ }
+ }
+ else
+ {
+ /* Call user error callback */
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Error Callback */
+ husart->ErrorCallback(husart);
+#else
+ /* Call legacy weak Error Callback */
+ HAL_USART_ErrorCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Call user error callback */
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Error Callback */
+ husart->ErrorCallback(husart);
+#else
+ /* Call legacy weak Error Callback */
+ HAL_USART_ErrorCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Non Blocking error : transfer could go on.
+ Error is notified to user through user error callback */
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Error Callback */
+ husart->ErrorCallback(husart);
+#else
+ /* Call legacy weak Error Callback */
+ HAL_USART_ErrorCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+ }
+ }
+ return;
+
+ } /* End if some error occurs */
+
+
+ /* USART in mode Transmitter ------------------------------------------------*/
+ if (((isrflags & USART_ISR_TXE_TXFNF) != 0U)
+ && (((cr1its & USART_CR1_TXEIE_TXFNFIE) != 0U)
+ || ((cr3its & USART_CR3_TXFTIE) != 0U)))
+ {
+ if (husart->TxISR != NULL)
+ {
+ husart->TxISR(husart);
+ }
+ return;
+ }
+
+ /* USART in mode Transmitter (transmission end) -----------------------------*/
+ if (((isrflags & USART_ISR_TC) != 0U) && ((cr1its & USART_CR1_TCIE) != 0U))
+ {
+ USART_EndTransmit_IT(husart);
+ return;
+ }
+
+ /* USART TX Fifo Empty occurred ----------------------------------------------*/
+ if (((isrflags & USART_ISR_TXFE) != 0U) && ((cr1its & USART_CR1_TXFEIE) != 0U))
+ {
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Fifo Empty Callback */
+ husart->TxFifoEmptyCallback(husart);
+#else
+ /* Call legacy weak Tx Fifo Empty Callback */
+ HAL_USARTEx_TxFifoEmptyCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ return;
+ }
+
+ /* USART RX Fifo Full occurred ----------------------------------------------*/
+ if (((isrflags & USART_ISR_RXFF) != 0U) && ((cr1its & USART_CR1_RXFFIE) != 0U))
+ {
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Fifo Full Callback */
+ husart->RxFifoFullCallback(husart);
+#else
+ /* Call legacy weak Rx Fifo Full Callback */
+ HAL_USARTEx_RxFifoFullCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ return;
+ }
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USART_TxCpltCallback(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_USART_TxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USART_TxHalfCpltCallback(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_USART_TxHalfCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USART_RxCpltCallback(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_USART_RxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Rx Half Transfer completed callback.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USART_RxHalfCpltCallback(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_USART_RxHalfCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx/Rx Transfers completed callback for the non-blocking process.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USART_TxRxCpltCallback(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_USART_TxRxCpltCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief USART error callback.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USART_ErrorCallback(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_USART_ErrorCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief USART Abort Complete callback.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USART_AbortCpltCallback(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_USART_AbortCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Exported_Functions_Group4 Peripheral State and Error functions
+ * @brief USART Peripheral State and Error functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Error functions #####
+ ==============================================================================
+ [..]
+ This subsection provides functions allowing to :
+ (+) Return the USART handle state
+ (+) Return the USART handle error code
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Return the USART handle state.
+ * @param husart pointer to a USART_HandleTypeDef structure that contains
+ * the configuration information for the specified USART.
+ * @retval USART handle state
+ */
+HAL_USART_StateTypeDef HAL_USART_GetState(USART_HandleTypeDef *husart)
+{
+ return husart->State;
+}
+
+/**
+ * @brief Return the USART error code.
+ * @param husart pointer to a USART_HandleTypeDef structure that contains
+ * the configuration information for the specified USART.
+ * @retval USART handle Error Code
+ */
+uint32_t HAL_USART_GetError(USART_HandleTypeDef *husart)
+{
+ return husart->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Private_Functions USART Private Functions
+ * @{
+ */
+
+/**
+ * @brief Initialize the callbacks to their default values.
+ * @param husart USART handle.
+ * @retval none
+ */
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart)
+{
+ /* Init the USART Callback settings */
+ husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
+ husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */
+ husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ husart->RxFifoFullCallback = HAL_USARTEx_RxFifoFullCallback; /* Legacy weak RxFifoFullCallback */
+ husart->TxFifoEmptyCallback = HAL_USARTEx_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */
+}
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+
+/**
+ * @brief End ongoing transfer on USART peripheral (following error detection or Transfer completion).
+ * @param husart USART handle.
+ * @retval None
+ */
+static void USART_EndTransfer(USART_HandleTypeDef *husart)
+{
+ /* Disable TXEIE, TCIE, RXNE, RXFT, TXFT, PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE |
+ USART_CR1_TCIE));
+ CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE));
+
+ /* At end of process, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+}
+
+/**
+ * @brief DMA USART transmit process complete callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent);
+
+ /* DMA Normal mode */
+ if (hdma->Init.Mode != DMA_CIRCULAR)
+ {
+ husart->TxXferCount = 0U;
+
+ if (husart->State == HAL_USART_STATE_BUSY_TX)
+ {
+ /* Disable the DMA transfer for transmit request by resetting the DMAT bit
+ in the USART CR3 register */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+
+ /* Enable the USART Transmit Complete Interrupt */
+ __HAL_USART_ENABLE_IT(husart, USART_IT_TC);
+ }
+ }
+ /* DMA Circular mode */
+ else
+ {
+ if (husart->State == HAL_USART_STATE_BUSY_TX)
+ {
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Complete Callback */
+ husart->TxCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Complete Callback */
+ HAL_USART_TxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @brief DMA USART transmit process half complete callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent);
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Half Complete Callback */
+ husart->TxHalfCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Half Complete Callback */
+ HAL_USART_TxHalfCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA USART receive process complete callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent);
+
+ /* DMA Normal mode */
+ if (hdma->Init.Mode != DMA_CIRCULAR)
+ {
+ husart->RxXferCount = 0U;
+
+ /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
+ CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Disable the DMA RX transfer for the receiver request by resetting the DMAR bit
+ in USART CR3 register */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
+ /* similarly, disable the DMA TX transfer that was started to provide the
+ clock to the slave device */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
+
+ if (husart->State == HAL_USART_STATE_BUSY_RX)
+ {
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Complete Callback */
+ husart->RxCpltCallback(husart);
+#else
+ /* Call legacy weak Rx Complete Callback */
+ HAL_USART_RxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ /* The USART state is HAL_USART_STATE_BUSY_TX_RX */
+ else
+ {
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Rx Complete Callback */
+ husart->TxRxCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Rx Complete Callback */
+ HAL_USART_TxRxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ husart->State = HAL_USART_STATE_READY;
+ }
+ /* DMA circular mode */
+ else
+ {
+ if (husart->State == HAL_USART_STATE_BUSY_RX)
+ {
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Complete Callback */
+ husart->RxCpltCallback(husart);
+#else
+ /* Call legacy weak Rx Complete Callback */
+ HAL_USART_RxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ /* The USART state is HAL_USART_STATE_BUSY_TX_RX */
+ else
+ {
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Rx Complete Callback */
+ husart->TxRxCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Rx Complete Callback */
+ HAL_USART_TxRxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @brief DMA USART receive process half complete callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent);
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Half Complete Callback */
+ husart->RxHalfCpltCallback(husart);
+#else
+ /* Call legacy weak Rx Half Complete Callback */
+ HAL_USART_RxHalfCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA USART communication error callback.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void USART_DMAError(DMA_HandleTypeDef *hdma)
+{
+ USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent);
+
+ husart->RxXferCount = 0U;
+ husart->TxXferCount = 0U;
+ USART_EndTransfer(husart);
+
+ husart->ErrorCode |= HAL_USART_ERROR_DMA;
+ husart->State = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Error Callback */
+ husart->ErrorCallback(husart);
+#else
+ /* Call legacy weak Error Callback */
+ HAL_USART_ErrorCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA USART communication abort callback, when initiated by HAL services on Error
+ * (To be called at end of DMA Abort procedure following error occurrence).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma)
+{
+ USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent);
+ husart->RxXferCount = 0U;
+ husart->TxXferCount = 0U;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Error Callback */
+ husart->ErrorCallback(husart);
+#else
+ /* Call legacy weak Error Callback */
+ HAL_USART_ErrorCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA USART Tx communication abort callback, when initiated by user
+ * (To be called at end of DMA Tx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Rx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent);
+
+ husart->hdmatx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (husart->hdmarx != NULL)
+ {
+ if (husart->hdmarx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
+ husart->TxXferCount = 0U;
+ husart->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_OREF | USART_CLEAR_NEF | USART_CLEAR_PEF | USART_CLEAR_FEF);
+
+ /* Restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Complete Callback */
+ husart->AbortCpltCallback(husart);
+#else
+ /* Call legacy weak Abort Complete Callback */
+ HAL_USART_AbortCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+
+}
+
+
+/**
+ * @brief DMA USART Rx communication abort callback, when initiated by user
+ * (To be called at end of DMA Rx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Tx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent);
+
+ husart->hdmarx->XferAbortCallback = NULL;
+
+ /* Check if an Abort process is still ongoing */
+ if (husart->hdmatx != NULL)
+ {
+ if (husart->hdmatx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
+ husart->TxXferCount = 0U;
+ husart->RxXferCount = 0U;
+
+ /* Reset errorCode */
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+
+ /* Clear the Error flags in the ICR register */
+ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_OREF | USART_CLEAR_NEF | USART_CLEAR_PEF | USART_CLEAR_FEF);
+
+ /* Restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Abort Complete Callback */
+ husart->AbortCpltCallback(husart);
+#else
+ /* Call legacy weak Abort Complete Callback */
+ HAL_USART_AbortCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+}
+
+
+/**
+ * @brief Handle USART Communication Timeout.
+ * @param husart USART handle.
+ * @param Flag Specifies the USART flag to check.
+ * @param Status the Flag status (SET or RESET).
+ * @param Tickstart Tick start value
+ * @param Timeout timeout duration.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status,
+ uint32_t Tickstart, uint32_t Timeout)
+{
+ /* Wait until flag is set */
+ while ((__HAL_USART_GET_FLAG(husart, Flag) ? SET : RESET) == Status)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the USART peripheral.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef USART_SetConfig(USART_HandleTypeDef *husart)
+{
+ uint32_t tmpreg;
+ USART_ClockSourceTypeDef clocksource;
+ HAL_StatusTypeDef ret = HAL_OK;
+ uint16_t brrtemp;
+ uint32_t usartdiv = 0x00000000;
+ PLL2_ClocksTypeDef pll2_clocks;
+ PLL3_ClocksTypeDef pll3_clocks;
+ uint32_t pclk;
+
+ /* Check the parameters */
+ assert_param(IS_USART_POLARITY(husart->Init.CLKPolarity));
+ assert_param(IS_USART_PHASE(husart->Init.CLKPhase));
+ assert_param(IS_USART_LASTBIT(husart->Init.CLKLastBit));
+ assert_param(IS_USART_BAUDRATE(husart->Init.BaudRate));
+ assert_param(IS_USART_WORD_LENGTH(husart->Init.WordLength));
+ assert_param(IS_USART_STOPBITS(husart->Init.StopBits));
+ assert_param(IS_USART_PARITY(husart->Init.Parity));
+ assert_param(IS_USART_MODE(husart->Init.Mode));
+ assert_param(IS_USART_PRESCALER(husart->Init.ClockPrescaler));
+
+ /*-------------------------- USART CR1 Configuration -----------------------*/
+ /* Clear M, PCE, PS, TE and RE bits and configure
+ * the USART Word Length, Parity and Mode:
+ * set the M bits according to husart->Init.WordLength value
+ * set PCE and PS bits according to husart->Init.Parity value
+ * set TE and RE bits according to husart->Init.Mode value
+ * force OVER8 to 1 to allow to reach the maximum speed (Fclock/8) */
+ tmpreg = (uint32_t)husart->Init.WordLength | husart->Init.Parity | husart->Init.Mode | USART_CR1_OVER8;
+ MODIFY_REG(husart->Instance->CR1, USART_CR1_FIELDS, tmpreg);
+
+ /*---------------------------- USART CR2 Configuration ---------------------*/
+ /* Clear and configure the USART Clock, CPOL, CPHA, LBCL STOP and SLVEN bits:
+ * set CPOL bit according to husart->Init.CLKPolarity value
+ * set CPHA bit according to husart->Init.CLKPhase value
+ * set LBCL bit according to husart->Init.CLKLastBit value (used in SPI master mode only)
+ * set STOP[13:12] bits according to husart->Init.StopBits value */
+ tmpreg = (uint32_t)(USART_CLOCK_ENABLE);
+ tmpreg |= (uint32_t)husart->Init.CLKLastBit;
+ tmpreg |= ((uint32_t)husart->Init.CLKPolarity | (uint32_t)husart->Init.CLKPhase);
+ tmpreg |= (uint32_t)husart->Init.StopBits;
+ MODIFY_REG(husart->Instance->CR2, USART_CR2_FIELDS, tmpreg);
+
+ /*-------------------------- USART PRESC Configuration -----------------------*/
+ /* Configure
+ * - USART Clock Prescaler : set PRESCALER according to husart->Init.ClockPrescaler value */
+ MODIFY_REG(husart->Instance->PRESC, USART_PRESC_PRESCALER, husart->Init.ClockPrescaler);
+
+ /*-------------------------- USART BRR Configuration -----------------------*/
+ /* BRR is filled-up according to OVER8 bit setting which is forced to 1 */
+ USART_GETCLOCKSOURCE(husart, clocksource);
+
+ switch (clocksource)
+ {
+ case USART_CLOCKSOURCE_D2PCLK1:
+ pclk = HAL_RCC_GetPCLK1Freq();
+ usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate, husart->Init.ClockPrescaler));
+ break;
+ case USART_CLOCKSOURCE_D2PCLK2:
+ pclk = HAL_RCC_GetPCLK2Freq();
+ usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate, husart->Init.ClockPrescaler));
+ break;
+ case USART_CLOCKSOURCE_PLL2:
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pll2_clocks.PLL2_Q_Frequency, husart->Init.BaudRate, husart->Init.ClockPrescaler));
+ break;
+ case USART_CLOCKSOURCE_PLL3:
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pll3_clocks.PLL3_Q_Frequency, husart->Init.BaudRate, husart->Init.ClockPrescaler));
+ break;
+ case USART_CLOCKSOURCE_HSI:
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ usartdiv = (uint32_t)(USART_DIV_SAMPLING8((HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3U)), husart->Init.BaudRate, husart->Init.ClockPrescaler));
+ }
+ else
+ {
+ usartdiv = (uint32_t)(USART_DIV_SAMPLING8(HSI_VALUE, husart->Init.BaudRate, husart->Init.ClockPrescaler));
+ }
+ break;
+ case USART_CLOCKSOURCE_CSI:
+ usartdiv = (uint32_t)(USART_DIV_SAMPLING8(CSI_VALUE, husart->Init.BaudRate, husart->Init.ClockPrescaler));
+ break;
+ case USART_CLOCKSOURCE_LSE:
+ usartdiv = (uint32_t)(USART_DIV_SAMPLING8(LSE_VALUE, husart->Init.BaudRate, husart->Init.ClockPrescaler));
+ break;
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ /* USARTDIV must be greater than or equal to 0d16 and smaller than or equal to ffff */
+ if ((usartdiv >= USART_BRR_MIN) && (usartdiv <= USART_BRR_MAX))
+ {
+ brrtemp = (uint16_t)(usartdiv & 0xFFF0U);
+ brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U);
+ husart->Instance->BRR = brrtemp;
+ }
+ else
+ {
+ ret = HAL_ERROR;
+ }
+
+ /* Initialize the number of data to process during RX/TX ISR execution */
+ husart->NbTxDataToProcess = 1U;
+ husart->NbRxDataToProcess = 1U;
+
+ /* Clear ISR function pointers */
+ husart->RxISR = NULL;
+ husart->TxISR = NULL;
+
+ return ret;
+}
+
+/**
+ * @brief Check the USART Idle State.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef USART_CheckIdleState(USART_HandleTypeDef *husart)
+{
+ uint32_t tickstart;
+
+ /* Initialize the USART ErrorCode */
+ husart->ErrorCode = HAL_USART_ERROR_NONE;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Check if the Transmitter is enabled */
+ if ((husart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE)
+ {
+ /* Wait until TEACK flag is set */
+ if (USART_WaitOnFlagUntilTimeout(husart, USART_ISR_TEACK, RESET, tickstart, USART_TEACK_REACK_TIMEOUT) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Check if the Receiver is enabled */
+ if ((husart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE)
+ {
+ /* Wait until REACK flag is set */
+ if (USART_WaitOnFlagUntilTimeout(husart, USART_ISR_REACK, RESET, tickstart, USART_TEACK_REACK_TIMEOUT) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Initialize the USART state*/
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Simplex send an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_USART_Transmit_IT().
+ * @note The USART errors are not managed to avoid the overrun error.
+ * @note ISR function executed when FIFO mode is disabled and when the
+ * data word length is less than 9 bits long.
+ * @param husart USART handle.
+ * @retval None
+ */
+static void USART_TxISR_8BIT(USART_HandleTypeDef *husart)
+{
+ const HAL_USART_StateTypeDef state = husart->State;
+
+ /* Check that a Tx process is ongoing */
+ if ((state == HAL_USART_STATE_BUSY_TX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ if (husart->TxXferCount == 0U)
+ {
+ /* Disable the USART Transmit data register empty interrupt */
+ __HAL_USART_DISABLE_IT(husart, USART_IT_TXE);
+
+ /* Enable the USART Transmit Complete Interrupt */
+ __HAL_USART_ENABLE_IT(husart, USART_IT_TC);
+ }
+ else
+ {
+ husart->Instance->TDR = (uint8_t)(*husart->pTxBuffPtr & (uint8_t)0xFF);
+ husart->pTxBuffPtr++;
+ husart->TxXferCount--;
+ }
+ }
+}
+
+/**
+ * @brief Simplex send an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_USART_Transmit_IT().
+ * @note The USART errors are not managed to avoid the overrun error.
+ * @note ISR function executed when FIFO mode is disabled and when the
+ * data word length is 9 bits long.
+ * @param husart USART handle.
+ * @retval None
+ */
+static void USART_TxISR_16BIT(USART_HandleTypeDef *husart)
+{
+ const HAL_USART_StateTypeDef state = husart->State;
+ uint16_t *tmp;
+
+ if ((state == HAL_USART_STATE_BUSY_TX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ if (husart->TxXferCount == 0U)
+ {
+ /* Disable the USART Transmit data register empty interrupt */
+ __HAL_USART_DISABLE_IT(husart, USART_IT_TXE);
+
+ /* Enable the USART Transmit Complete Interrupt */
+ __HAL_USART_ENABLE_IT(husart, USART_IT_TC);
+ }
+ else
+ {
+ tmp = (uint16_t *) husart->pTxBuffPtr;
+ husart->Instance->TDR = (uint16_t)(*tmp & 0x01FFU);
+ husart->pTxBuffPtr += 2U;
+ husart->TxXferCount--;
+ }
+ }
+}
+
+/**
+ * @brief Simplex send an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_USART_Transmit_IT().
+ * @note The USART errors are not managed to avoid the overrun error.
+ * @note ISR function executed when FIFO mode is enabled and when the
+ * data word length is less than 9 bits long.
+ * @param husart USART handle.
+ * @retval None
+ */
+static void USART_TxISR_8BIT_FIFOEN(USART_HandleTypeDef *husart)
+{
+ const HAL_USART_StateTypeDef state = husart->State;
+ uint16_t nb_tx_data;
+
+ /* Check that a Tx process is ongoing */
+ if ((state == HAL_USART_STATE_BUSY_TX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ for (nb_tx_data = husart->NbTxDataToProcess ; nb_tx_data > 0U ; nb_tx_data--)
+ {
+ if (husart->TxXferCount == 0U)
+ {
+ /* Disable the TX FIFO threshold interrupt */
+ __HAL_USART_DISABLE_IT(husart, USART_IT_TXFT);
+
+ /* Enable the USART Transmit Complete Interrupt */
+ __HAL_USART_ENABLE_IT(husart, USART_IT_TC);
+
+ break; /* force exit loop */
+ }
+ else if (__HAL_USART_GET_FLAG(husart, USART_FLAG_TXFNF) == SET)
+ {
+ husart->Instance->TDR = (uint8_t)(*husart->pTxBuffPtr & (uint8_t)0xFF);
+ husart->pTxBuffPtr++;
+ husart->TxXferCount--;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+}
+
+/**
+ * @brief Simplex send an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_USART_Transmit_IT().
+ * @note The USART errors are not managed to avoid the overrun error.
+ * @note ISR function executed when FIFO mode is enabled and when the
+ * data word length is 9 bits long.
+ * @param husart USART handle.
+ * @retval None
+ */
+static void USART_TxISR_16BIT_FIFOEN(USART_HandleTypeDef *husart)
+{
+ const HAL_USART_StateTypeDef state = husart->State;
+ uint16_t *tmp;
+ uint16_t nb_tx_data;
+
+ /* Check that a Tx process is ongoing */
+ if ((state == HAL_USART_STATE_BUSY_TX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ for (nb_tx_data = husart->NbTxDataToProcess ; nb_tx_data > 0U ; nb_tx_data--)
+ {
+ if (husart->TxXferCount == 0U)
+ {
+ /* Disable the TX FIFO threshold interrupt */
+ __HAL_USART_DISABLE_IT(husart, USART_IT_TXFT);
+
+ /* Enable the USART Transmit Complete Interrupt */
+ __HAL_USART_ENABLE_IT(husart, USART_IT_TC);
+
+ break; /* force exit loop */
+ }
+ else if (__HAL_USART_GET_FLAG(husart, USART_FLAG_TXFNF) == SET)
+ {
+ tmp = (uint16_t *) husart->pTxBuffPtr;
+ husart->Instance->TDR = (uint16_t)(*tmp & 0x01FFU);
+ husart->pTxBuffPtr += 2U;
+ husart->TxXferCount--;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+}
+
+/**
+ * @brief Wraps up transmission in non-blocking mode.
+ * @param husart Pointer to a USART_HandleTypeDef structure that contains
+ * the configuration information for the specified USART module.
+ * @retval None
+ */
+static void USART_EndTransmit_IT(USART_HandleTypeDef *husart)
+{
+ /* Disable the USART Transmit Complete Interrupt */
+ __HAL_USART_DISABLE_IT(husart, USART_IT_TC);
+
+ /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
+ __HAL_USART_DISABLE_IT(husart, USART_IT_ERR);
+
+ /* Clear TxISR function pointer */
+ husart->TxISR = NULL;
+
+ if (husart->State == HAL_USART_STATE_BUSY_TX)
+ {
+ /* Clear overrun flag and discard the received data */
+ __HAL_USART_CLEAR_OREFLAG(husart);
+ __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST);
+
+ /* Tx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Complete Callback */
+ husart->TxCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Complete Callback */
+ HAL_USART_TxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else if (husart->RxXferCount == 0U)
+ {
+ /* TxRx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Rx Complete Callback */
+ husart->TxRxCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Rx Complete Callback */
+ HAL_USART_TxRxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+
+/**
+ * @brief Simplex receive an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_USART_Receive_IT().
+ * @note ISR function executed when FIFO mode is disabled and when the
+ * data word length is less than 9 bits long.
+ * @param husart USART handle
+ * @retval None
+ */
+static void USART_RxISR_8BIT(USART_HandleTypeDef *husart)
+{
+ const HAL_USART_StateTypeDef state = husart->State;
+ uint16_t txdatacount;
+ uint16_t uhMask = husart->Mask;
+ uint32_t txftie;
+
+ if ((state == HAL_USART_STATE_BUSY_RX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ *husart->pRxBuffPtr = (uint8_t)(husart->Instance->RDR & (uint8_t)uhMask);
+ husart->pRxBuffPtr++;
+ husart->RxXferCount--;
+
+ if (husart->RxXferCount == 0U)
+ {
+ /* Disable the USART Parity Error Interrupt and RXNE interrupt*/
+ CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+
+ /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Clear RxISR function pointer */
+ husart->RxISR = NULL;
+
+ /* txftie and txdatacount are temporary variables for MISRAC2012-Rule-13.5 */
+ txftie = READ_BIT(husart->Instance->CR3, USART_CR3_TXFTIE);
+ txdatacount = husart->TxXferCount;
+
+ if (state == HAL_USART_STATE_BUSY_RX)
+ {
+ /* Clear SPI slave underrun flag and discard transmit data */
+ if (husart->SlaveMode == USART_SLAVEMODE_ENABLE)
+ {
+ __HAL_USART_CLEAR_UDRFLAG(husart);
+ __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Rx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Complete Callback */
+ husart->RxCpltCallback(husart);
+#else
+ /* Call legacy weak Rx Complete Callback */
+ HAL_USART_RxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) &&
+ (txftie != USART_CR3_TXFTIE) &&
+ (txdatacount == 0U))
+ {
+ /* TxRx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Rx Complete Callback */
+ husart->TxRxCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Rx Complete Callback */
+ HAL_USART_TxRxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ else if ((state == HAL_USART_STATE_BUSY_RX) &&
+ (husart->SlaveMode == USART_SLAVEMODE_DISABLE))
+ {
+ /* Send dummy byte in order to generate the clock for the Slave to Send the next data */
+ husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+}
+
+/**
+ * @brief Simplex receive an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_USART_Receive_IT().
+ * @note ISR function executed when FIFO mode is disabled and when the
+ * data word length is 9 bits long.
+ * @param husart USART handle
+ * @retval None
+ */
+static void USART_RxISR_16BIT(USART_HandleTypeDef *husart)
+{
+ const HAL_USART_StateTypeDef state = husart->State;
+ uint16_t txdatacount;
+ uint16_t *tmp;
+ uint16_t uhMask = husart->Mask;
+ uint32_t txftie;
+
+ if ((state == HAL_USART_STATE_BUSY_RX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ tmp = (uint16_t *) husart->pRxBuffPtr;
+ *tmp = (uint16_t)(husart->Instance->RDR & uhMask);
+ husart->pRxBuffPtr += 2U;
+ husart->RxXferCount--;
+
+ if (husart->RxXferCount == 0U)
+ {
+ /* Disable the USART Parity Error Interrupt and RXNE interrupt*/
+ CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
+
+ /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
+
+ /* Clear RxISR function pointer */
+ husart->RxISR = NULL;
+
+ /* txftie and txdatacount are temporary variables for MISRAC2012-Rule-13.5 */
+ txftie = READ_BIT(husart->Instance->CR3, USART_CR3_TXFTIE);
+ txdatacount = husart->TxXferCount;
+
+ if (state == HAL_USART_STATE_BUSY_RX)
+ {
+ /* Clear SPI slave underrun flag and discard transmit data */
+ if (husart->SlaveMode == USART_SLAVEMODE_ENABLE)
+ {
+ __HAL_USART_CLEAR_UDRFLAG(husart);
+ __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Rx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Complete Callback */
+ husart->RxCpltCallback(husart);
+#else
+ /* Call legacy weak Rx Complete Callback */
+ HAL_USART_RxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) &&
+ (txftie != USART_CR3_TXFTIE) &&
+ (txdatacount == 0U))
+ {
+ /* TxRx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Rx Complete Callback */
+ husart->TxRxCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Rx Complete Callback */
+ HAL_USART_TxRxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ else if ((state == HAL_USART_STATE_BUSY_RX) &&
+ (husart->SlaveMode == USART_SLAVEMODE_DISABLE))
+ {
+ /* Send dummy byte in order to generate the clock for the Slave to Send the next data */
+ husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+}
+
+/**
+ * @brief Simplex receive an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_USART_Receive_IT().
+ * @note ISR function executed when FIFO mode is enabled and when the
+ * data word length is less than 9 bits long.
+ * @param husart USART handle
+ * @retval None
+ */
+static void USART_RxISR_8BIT_FIFOEN(USART_HandleTypeDef *husart)
+{
+ HAL_USART_StateTypeDef state = husart->State;
+ uint16_t txdatacount;
+ uint16_t rxdatacount;
+ uint16_t uhMask = husart->Mask;
+ uint16_t nb_rx_data;
+ uint32_t txftie;
+
+ /* Check that a Rx process is ongoing */
+ if ((state == HAL_USART_STATE_BUSY_RX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ for (nb_rx_data = husart->NbRxDataToProcess ; nb_rx_data > 0U ; nb_rx_data--)
+ {
+ if (__HAL_USART_GET_FLAG(husart, USART_FLAG_RXFNE) == SET)
+ {
+ *husart->pRxBuffPtr = (uint8_t)(husart->Instance->RDR & (uint8_t)(uhMask & 0xFFU));
+ husart->pRxBuffPtr++;
+ husart->RxXferCount--;
+
+ if (husart->RxXferCount == 0U)
+ {
+ /* Disable the USART Parity Error Interrupt */
+ CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
+
+ /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) and RX FIFO Threshold interrupt */
+ CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE));
+
+ /* Clear RxISR function pointer */
+ husart->RxISR = NULL;
+
+ /* txftie and txdatacount are temporary variables for MISRAC2012-Rule-13.5 */
+ txftie = READ_BIT(husart->Instance->CR3, USART_CR3_TXFTIE);
+ txdatacount = husart->TxXferCount;
+
+ if (state == HAL_USART_STATE_BUSY_RX)
+ {
+ /* Clear SPI slave underrun flag and discard transmit data */
+ if (husart->SlaveMode == USART_SLAVEMODE_ENABLE)
+ {
+ __HAL_USART_CLEAR_UDRFLAG(husart);
+ __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Rx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+ state = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Complete Callback */
+ husart->RxCpltCallback(husart);
+#else
+ /* Call legacy weak Rx Complete Callback */
+ HAL_USART_RxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) &&
+ (txftie != USART_CR3_TXFTIE) &&
+ (txdatacount == 0U))
+ {
+ /* TxRx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+ state = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Rx Complete Callback */
+ husart->TxRxCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Rx Complete Callback */
+ HAL_USART_TxRxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ else if ((state == HAL_USART_STATE_BUSY_RX) &&
+ (husart->SlaveMode == USART_SLAVEMODE_DISABLE))
+ {
+ /* Send dummy byte in order to generate the clock for the Slave to Send the next data */
+ husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+
+ /* When remaining number of bytes to receive is less than the RX FIFO
+ threshold, next incoming frames are processed as if FIFO mode was
+ disabled (i.e. one interrupt per received frame).
+ */
+ rxdatacount = husart->RxXferCount;
+ if (((rxdatacount != 0U)) && (rxdatacount < husart->NbRxDataToProcess))
+ {
+ /* Disable the USART RXFT interrupt*/
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_RXFTIE);
+
+ /* Update the RxISR function pointer */
+ husart->RxISR = USART_RxISR_8BIT;
+
+ /* Enable the USART Data Register Not Empty interrupt */
+ SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);
+
+ if ((husart->TxXferCount == 0U) &&
+ (state == HAL_USART_STATE_BUSY_TX_RX) &&
+ (husart->SlaveMode == USART_SLAVEMODE_DISABLE))
+ {
+ /* Send dummy byte in order to generate the clock for the Slave to Send the next data */
+ husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF);
+ }
+ }
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST);
+ }
+}
+
+/**
+ * @brief Simplex receive an amount of data in non-blocking mode.
+ * @note Function called under interruption only, once
+ * interruptions have been enabled by HAL_USART_Receive_IT().
+ * @note ISR function executed when FIFO mode is enabled and when the
+ * data word length is 9 bits long.
+ * @param husart USART handle
+ * @retval None
+ */
+static void USART_RxISR_16BIT_FIFOEN(USART_HandleTypeDef *husart)
+{
+ HAL_USART_StateTypeDef state = husart->State;
+ uint16_t txdatacount;
+ uint16_t rxdatacount;
+ uint16_t *tmp;
+ uint16_t uhMask = husart->Mask;
+ uint16_t nb_rx_data;
+ uint32_t txftie;
+
+ /* Check that a Tx process is ongoing */
+ if ((state == HAL_USART_STATE_BUSY_RX) ||
+ (state == HAL_USART_STATE_BUSY_TX_RX))
+ {
+ for (nb_rx_data = husart->NbRxDataToProcess ; nb_rx_data > 0U ; nb_rx_data--)
+ {
+ if (__HAL_USART_GET_FLAG(husart, USART_FLAG_RXFNE) == SET)
+ {
+ tmp = (uint16_t *) husart->pRxBuffPtr;
+ *tmp = (uint16_t)(husart->Instance->RDR & uhMask);
+ husart->pRxBuffPtr += 2U;
+ husart->RxXferCount--;
+
+ if (husart->RxXferCount == 0U)
+ {
+ /* Disable the USART Parity Error Interrupt */
+ CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
+
+ /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) and RX FIFO Threshold interrupt */
+ CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE));
+
+ /* Clear RxISR function pointer */
+ husart->RxISR = NULL;
+
+ /* txftie and txdatacount are temporary variables for MISRAC2012-Rule-13.5 */
+ txftie = READ_BIT(husart->Instance->CR3, USART_CR3_TXFTIE);
+ txdatacount = husart->TxXferCount;
+
+ if (state == HAL_USART_STATE_BUSY_RX)
+ {
+ /* Clear SPI slave underrun flag and discard transmit data */
+ if (husart->SlaveMode == USART_SLAVEMODE_ENABLE)
+ {
+ __HAL_USART_CLEAR_UDRFLAG(husart);
+ __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST);
+ }
+
+ /* Rx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+ state = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Rx Complete Callback */
+ husart->RxCpltCallback(husart);
+#else
+ /* Call legacy weak Rx Complete Callback */
+ HAL_USART_RxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) &&
+ (txftie != USART_CR3_TXFTIE) &&
+ (txdatacount == 0U))
+ {
+ /* TxRx process is completed, restore husart->State to Ready */
+ husart->State = HAL_USART_STATE_READY;
+ state = HAL_USART_STATE_READY;
+
+#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
+ /* Call registered Tx Rx Complete Callback */
+ husart->TxRxCpltCallback(husart);
+#else
+ /* Call legacy weak Tx Rx Complete Callback */
+ HAL_USART_TxRxCpltCallback(husart);
+#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ else if ((state == HAL_USART_STATE_BUSY_RX) &&
+ (husart->SlaveMode == USART_SLAVEMODE_DISABLE))
+ {
+ /* Send dummy byte in order to generate the clock for the Slave to Send the next data */
+ husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+ }
+
+ /* When remaining number of bytes to receive is less than the RX FIFO
+ threshold, next incoming frames are processed as if FIFO mode was
+ disabled (i.e. one interrupt per received frame).
+ */
+ rxdatacount = husart->RxXferCount;
+ if (((rxdatacount != 0U)) && (rxdatacount < husart->NbRxDataToProcess))
+ {
+ /* Disable the USART RXFT interrupt*/
+ CLEAR_BIT(husart->Instance->CR3, USART_CR3_RXFTIE);
+
+ /* Update the RxISR function pointer */
+ husart->RxISR = USART_RxISR_16BIT;
+
+ /* Enable the USART Data Register Not Empty interrupt */
+ SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);
+
+ if ((husart->TxXferCount == 0U) &&
+ (state == HAL_USART_STATE_BUSY_TX_RX) &&
+ (husart->SlaveMode == USART_SLAVEMODE_DISABLE))
+ {
+ /* Send dummy byte in order to generate the clock for the Slave to Send the next data */
+ husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF);
+ }
+ }
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST);
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_USART_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_usart_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_usart_ex.c
new file mode 100644
index 0000000000..2732976f47
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_usart_ex.c
@@ -0,0 +1,538 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_usart_ex.c
+ * @author MCD Application Team
+ * @brief Extended USART HAL module driver.
+ * This file provides firmware functions to manage the following extended
+ * functionalities of the Universal Synchronous Receiver Transmitter Peripheral (USART).
+ * + Peripheral Control functions
+ *
+ *
+ @verbatim
+ ==============================================================================
+ ##### USART peripheral extended features #####
+ ==============================================================================
+
+ (#) FIFO mode enabling/disabling and RX/TX FIFO threshold programming.
+
+ -@- When USART operates in FIFO mode, FIFO mode must be enabled prior
+ starting RX/TX transfers. Also RX/TX FIFO thresholds must be
+ configured prior starting RX/TX transfers.
+
+ (#) Slave mode enabling/disabling and NSS pin configuration.
+
+ -@- When USART operates in Slave mode, Slave mode must be enabled prior
+ starting RX/TX transfers.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup USARTEx USARTEx
+ * @brief USART Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_USART_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/** @defgroup USARTEx_Private_Constants USARTEx Private Constants
+ * @{
+ */
+/* USART RX FIFO depth */
+#define RX_FIFO_DEPTH 8U
+
+/* USART TX FIFO depth */
+#define TX_FIFO_DEPTH 8U
+/**
+ * @}
+ */
+
+/* Private define ------------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup USARTEx_Private_Functions USARTEx Private Functions
+ * @{
+ */
+static void USARTEx_SetNbDataToProcess(USART_HandleTypeDef *husart);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup USARTEx_Exported_Functions USARTEx Exported Functions
+ * @{
+ */
+
+/** @defgroup USARTEx_Exported_Functions_Group1 IO operation functions
+ * @brief Extended USART Transmit/Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ This subsection provides a set of FIFO mode related callback functions.
+
+ (#) TX/RX Fifos Callbacks:
+ (+) HAL_USARTEx_RxFifoFullCallback()
+ (+) HAL_USARTEx_TxFifoEmptyCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief USART RX Fifo full callback.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USARTEx_RxFifoFullCallback(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_USARTEx_RxFifoFullCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief USART TX Fifo empty callback.
+ * @param husart USART handle.
+ * @retval None
+ */
+__weak void HAL_USARTEx_TxFifoEmptyCallback(USART_HandleTypeDef *husart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(husart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_USARTEx_TxFifoEmptyCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup USARTEx_Exported_Functions_Group2 Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides the following functions:
+ (+) HAL_USARTEx_EnableSPISlaveMode() API enables the SPI slave mode
+ (+) HAL_USARTEx_DisableSPISlaveMode() API disables the SPI slave mode
+ (+) HAL_USARTEx_ConfigNSS API configures the Slave Select input pin (NSS)
+ (+) HAL_USARTEx_EnableFifoMode() API enables the FIFO mode
+ (+) HAL_USARTEx_DisableFifoMode() API disables the FIFO mode
+ (+) HAL_USARTEx_SetTxFifoThreshold() API sets the TX FIFO threshold
+ (+) HAL_USARTEx_SetRxFifoThreshold() API sets the RX FIFO threshold
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable the SPI slave mode.
+ * @note When the USART operates in SPI slave mode, it handles data flow using
+ * the serial interface clock derived from the external SCLK signal
+ * provided by the external master SPI device.
+ * @note In SPI slave mode, the USART must be enabled before starting the master
+ * communications (or between frames while the clock is stable). Otherwise,
+ * if the USART slave is enabled while the master is in the middle of a
+ * frame, it will become desynchronized with the master.
+ * @note The data register of the slave needs to be ready before the first edge
+ * of the communication clock or before the end of the ongoing communication,
+ * otherwise the SPI slave will transmit zeros.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USARTEx_EnableSlaveMode(USART_HandleTypeDef *husart)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_SPI_SLAVE_INSTANCE(husart->Instance));
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->State = HAL_USART_STATE_BUSY;
+
+ /* Save actual USART configuration */
+ tmpcr1 = READ_REG(husart->Instance->CR1);
+
+ /* Disable USART */
+ __HAL_USART_DISABLE(husart);
+
+ /* In SPI slave mode mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bit in the USART_CR2 register
+ - HDSEL, SCEN and IREN bits in the USART_CR3 register.*/
+ CLEAR_BIT(husart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
+ CLEAR_BIT(husart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
+
+ /* Enable SPI slave mode */
+ SET_BIT(husart->Instance->CR2, USART_CR2_SLVEN);
+
+ /* Restore USART configuration */
+ WRITE_REG(husart->Instance->CR1, tmpcr1);
+
+ husart->SlaveMode = USART_SLAVEMODE_ENABLE;
+
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Enable USART */
+ __HAL_USART_ENABLE(husart);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the SPI slave mode.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USARTEx_DisableSlaveMode(USART_HandleTypeDef *husart)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_SPI_SLAVE_INSTANCE(husart->Instance));
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->State = HAL_USART_STATE_BUSY;
+
+ /* Save actual USART configuration */
+ tmpcr1 = READ_REG(husart->Instance->CR1);
+
+ /* Disable USART */
+ __HAL_USART_DISABLE(husart);
+
+ /* Disable SPI slave mode */
+ CLEAR_BIT(husart->Instance->CR2, USART_CR2_SLVEN);
+
+ /* Restore USART configuration */
+ WRITE_REG(husart->Instance->CR1, tmpcr1);
+
+ husart->SlaveMode = USART_SLAVEMODE_DISABLE;
+
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the Slave Select input pin (NSS).
+ * @note Software NSS management: SPI slave will always be selected and NSS
+ * input pin will be ignored.
+ * @note Hardware NSS management: the SPI slave selection depends on NSS
+ * input pin. The slave is selected when NSS is low and deselected when
+ * NSS is high.
+ * @param husart USART handle.
+ * @param NSSConfig NSS configuration.
+ * This parameter can be one of the following values:
+ * @arg @ref USART_NSS_HARD
+ * @arg @ref USART_NSS_SOFT
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USARTEx_ConfigNSS(USART_HandleTypeDef *husart, uint32_t NSSConfig)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_SPI_SLAVE_INSTANCE(husart->Instance));
+ assert_param(IS_USART_NSS(NSSConfig));
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->State = HAL_USART_STATE_BUSY;
+
+ /* Save actual USART configuration */
+ tmpcr1 = READ_REG(husart->Instance->CR1);
+
+ /* Disable USART */
+ __HAL_USART_DISABLE(husart);
+
+ /* Program DIS_NSS bit in the USART_CR2 register */
+ MODIFY_REG(husart->Instance->CR2, USART_CR2_DIS_NSS, NSSConfig);
+
+ /* Restore USART configuration */
+ WRITE_REG(husart->Instance->CR1, tmpcr1);
+
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the FIFO mode.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USARTEx_EnableFifoMode(USART_HandleTypeDef *husart)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(husart->Instance));
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->State = HAL_USART_STATE_BUSY;
+
+ /* Save actual USART configuration */
+ tmpcr1 = READ_REG(husart->Instance->CR1);
+
+ /* Disable USART */
+ __HAL_USART_DISABLE(husart);
+
+ /* Enable FIFO mode */
+ SET_BIT(tmpcr1, USART_CR1_FIFOEN);
+ husart->FifoMode = USART_FIFOMODE_ENABLE;
+
+ /* Restore USART configuration */
+ WRITE_REG(husart->Instance->CR1, tmpcr1);
+
+ /* Determine the number of data to process during RX/TX ISR execution */
+ USARTEx_SetNbDataToProcess(husart);
+
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the FIFO mode.
+ * @param husart USART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USARTEx_DisableFifoMode(USART_HandleTypeDef *husart)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(husart->Instance));
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->State = HAL_USART_STATE_BUSY;
+
+ /* Save actual USART configuration */
+ tmpcr1 = READ_REG(husart->Instance->CR1);
+
+ /* Disable USART */
+ __HAL_USART_DISABLE(husart);
+
+ /* Enable FIFO mode */
+ CLEAR_BIT(tmpcr1, USART_CR1_FIFOEN);
+ husart->FifoMode = USART_FIFOMODE_DISABLE;
+
+ /* Restore USART configuration */
+ WRITE_REG(husart->Instance->CR1, tmpcr1);
+
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the TXFIFO threshold.
+ * @param husart USART handle.
+ * @param Threshold TX FIFO threshold value
+ * This parameter can be one of the following values:
+ * @arg @ref USART_TXFIFO_THRESHOLD_1_8
+ * @arg @ref USART_TXFIFO_THRESHOLD_1_4
+ * @arg @ref USART_TXFIFO_THRESHOLD_1_2
+ * @arg @ref USART_TXFIFO_THRESHOLD_3_4
+ * @arg @ref USART_TXFIFO_THRESHOLD_7_8
+ * @arg @ref USART_TXFIFO_THRESHOLD_8_8
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USARTEx_SetTxFifoThreshold(USART_HandleTypeDef *husart, uint32_t Threshold)
+{
+ uint32_t tmpcr1;
+
+ /* Check parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(husart->Instance));
+ assert_param(IS_USART_TXFIFO_THRESHOLD(Threshold));
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->State = HAL_USART_STATE_BUSY;
+
+ /* Save actual USART configuration */
+ tmpcr1 = READ_REG(husart->Instance->CR1);
+
+ /* Disable USART */
+ __HAL_USART_DISABLE(husart);
+
+ /* Update TX threshold configuration */
+ MODIFY_REG(husart->Instance->CR3, USART_CR3_TXFTCFG, Threshold);
+
+ /* Determine the number of data to process during RX/TX ISR execution */
+ USARTEx_SetNbDataToProcess(husart);
+
+ /* Restore USART configuration */
+ WRITE_REG(husart->Instance->CR1, tmpcr1);
+
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the RXFIFO threshold.
+ * @param husart USART handle.
+ * @param Threshold RX FIFO threshold value
+ * This parameter can be one of the following values:
+ * @arg @ref USART_RXFIFO_THRESHOLD_1_8
+ * @arg @ref USART_RXFIFO_THRESHOLD_1_4
+ * @arg @ref USART_RXFIFO_THRESHOLD_1_2
+ * @arg @ref USART_RXFIFO_THRESHOLD_3_4
+ * @arg @ref USART_RXFIFO_THRESHOLD_7_8
+ * @arg @ref USART_RXFIFO_THRESHOLD_8_8
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_USARTEx_SetRxFifoThreshold(USART_HandleTypeDef *husart, uint32_t Threshold)
+{
+ uint32_t tmpcr1;
+
+ /* Check the parameters */
+ assert_param(IS_UART_FIFO_INSTANCE(husart->Instance));
+ assert_param(IS_USART_RXFIFO_THRESHOLD(Threshold));
+
+ /* Process Locked */
+ __HAL_LOCK(husart);
+
+ husart->State = HAL_USART_STATE_BUSY;
+
+ /* Save actual USART configuration */
+ tmpcr1 = READ_REG(husart->Instance->CR1);
+
+ /* Disable USART */
+ __HAL_USART_DISABLE(husart);
+
+ /* Update RX threshold configuration */
+ MODIFY_REG(husart->Instance->CR3, USART_CR3_RXFTCFG, Threshold);
+
+ /* Determine the number of data to process during RX/TX ISR execution */
+ USARTEx_SetNbDataToProcess(husart);
+
+ /* Restore USART configuration */
+ WRITE_REG(husart->Instance->CR1, tmpcr1);
+
+ husart->State = HAL_USART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(husart);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup USARTEx_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Calculate the number of data to process in RX/TX ISR.
+ * @note The RX FIFO depth and the TX FIFO depth is extracted from
+ * the USART configuration registers.
+ * @param husart USART handle.
+ * @retval None
+ */
+static void USARTEx_SetNbDataToProcess(USART_HandleTypeDef *husart)
+{
+ uint8_t rx_fifo_depth;
+ uint8_t tx_fifo_depth;
+ uint8_t rx_fifo_threshold;
+ uint8_t tx_fifo_threshold;
+ /* 2 0U/1U added for MISRAC2012-Rule-18.1_b and MISRAC2012-Rule-18.1_d */
+ uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
+ uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};
+
+ if (husart->FifoMode == USART_FIFOMODE_DISABLE)
+ {
+ husart->NbTxDataToProcess = 1U;
+ husart->NbRxDataToProcess = 1U;
+ }
+ else
+ {
+ rx_fifo_depth = RX_FIFO_DEPTH;
+ tx_fifo_depth = TX_FIFO_DEPTH;
+ rx_fifo_threshold = (uint8_t)((READ_BIT(husart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos) & 0xFFU);
+ tx_fifo_threshold = (uint8_t)((READ_BIT(husart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos) & 0xFFU);
+ husart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) / (uint16_t)denominator[tx_fifo_threshold];
+ husart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) / (uint16_t)denominator[rx_fifo_threshold];
+ }
+}
+/**
+ * @}
+ */
+
+#endif /* HAL_USART_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_wwdg.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_wwdg.c
new file mode 100644
index 0000000000..a4e29c5e0e
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_wwdg.c
@@ -0,0 +1,414 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_wwdg.c
+ * @author MCD Application Team
+ * @brief WWDG HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Window Watchdog (WWDG) peripheral:
+ * + Initialization and Configuration functions
+ * + IO operation functions
+ @verbatim
+ ==============================================================================
+ ##### WWDG Specific features #####
+ ==============================================================================
+ [..]
+ Once enabled the WWDG generates a system reset on expiry of a programmed
+ time period, unless the program refreshes the counter (T[6;0] downcounter)
+ before reaching 0x3F value (i.e. a reset is generated when the counter
+ value rolls down from 0x40 to 0x3F).
+
+ (+) An MCU reset is also generated if the counter value is refreshed
+ before the counter has reached the refresh window value. This
+ implies that the counter must be refreshed in a limited window.
+ (+) Once enabled the WWDG cannot be disabled except by a system reset.
+ (+) WWDGRST flag in RCC CSR register can be used to inform when a WWDG
+ reset occurs.
+ (+) The WWDG counter input clock is derived from the APB clock divided
+ by a programmable prescaler.
+ (+) WWDG clock (Hz) = PCLK1 / (4096 * Prescaler)
+ (+) WWDG timeout (mS) = 1000 * (T[5;0] + 1) / WWDG clock (Hz)
+ where T[5;0] are the lowest 6 bits of Counter.
+ (+) WWDG Counter refresh is allowed between the following limits :
+ (++) min time (mS) = 1000 * (Counter - Window) / WWDG clock
+ (++) max time (mS) = 1000 * (Counter - 0x40) / WWDG clock
+ (+) Typical values:
+ (++) Counter min (T[5;0] = 0x00) @56MHz (PCLK1) with zero prescaler:
+ max timeout before reset: approximately 73.14µs
+ (++) Counter max (T[5;0] = 0x3F) @56MHz (PCLK1) with prescaler dividing by 128:
+ max timeout before reset: approximately 599.18ms
+
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+
+ *** Common driver usage ***
+ ===========================
+
+ [..]
+ (+) Enable WWDG APB1 clock using __HAL_RCC_WWDG_CLK_ENABLE().
+ (+) Set the WWDG prescaler, refresh window and counter value
+ using HAL_WWDG_Init() function.
+ (+) Start the WWDG using HAL_WWDG_Start() function.
+ When the WWDG is enabled the counter value should be configured to
+ a value greater than 0x40 to prevent generating an immediate reset.
+ (+) Optionally you can enable the Early Wakeup Interrupt (EWI) which is
+ generated when the counter reaches 0x40, and then start the WWDG using
+ HAL_WWDG_Start_IT(). At EWI HAL_WWDG_WakeupCallback is executed and user can
+ add his own code by customization of callback HAL_WWDG_WakeupCallback.
+ Once enabled, EWI interrupt cannot be disabled except by a system reset.
+ (+) Then the application program must refresh the WWDG counter at regular
+ intervals during normal operation to prevent an MCU reset, using
+ HAL_WWDG_Refresh() function. This operation must occur only when
+ the counter is lower than the refresh window value already programmed.
+
+ *** Callback registration ***
+ =============================
+
+ [..]
+ The compilation define USE_HAL_WWDG_REGISTER_CALLBACKS when set to 1 allows
+ the user to configure dynamically the driver callbacks. Use Functions
+ @ref HAL_WWDG_RegisterCallback() to register a user callback.
+
+ (+) Function @ref HAL_WWDG_RegisterCallback() allows to register following
+ callbacks:
+ (++) EwiCallback : callback for Early WakeUp Interrupt.
+ (++) MspInitCallback : WWDG MspInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ (+) Use function @ref HAL_WWDG_UnRegisterCallback() to reset a callback to
+ the default weak (surcharged) function. @ref HAL_WWDG_UnRegisterCallback()
+ takes as parameters the HAL peripheral handle and the Callback ID.
+ This function allows to reset following callbacks:
+ (++) EwiCallback : callback for Early WakeUp Interrupt.
+ (++) MspInitCallback : WWDG MspInit.
+
+ [..]
+ When calling @ref HAL_WWDG_Init function, callbacks are reset to the
+ corresponding legacy weak (surcharged) functions:
+ @ref HAL_WWDG_EarlyWakeupCallback() and HAL_WWDG_MspInit() only if they have
+ not been registered before.
+
+ [..]
+ When compilation define USE_HAL_WWDG_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ *** WWDG HAL driver macros list ***
+ ===================================
+ [..]
+ Below the list of most used macros in WWDG HAL driver.
+ (+) __HAL_WWDG_ENABLE: Enable the WWDG peripheral
+ (+) __HAL_WWDG_GET_FLAG: Get the selected WWDG's flag status
+ (+) __HAL_WWDG_CLEAR_FLAG: Clear the WWDG's pending flags
+ (+) __HAL_WWDG_ENABLE_IT: Enable the WWDG early wakeup interrupt
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+/** @defgroup WWDG WWDG
+ * @brief WWDG HAL module driver.
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup WWDG_Exported_Functions WWDG Exported Functions
+ * @{
+ */
+
+/** @defgroup WWDG_Exported_Functions_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and Configuration functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and start the WWDG according to the specified parameters
+ in the WWDG_InitTypeDef of associated handle.
+ (+) Initialize the WWDG MSP.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the WWDG according to the specified.
+ * parameters in the WWDG_InitTypeDef of associated handle.
+ * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
+ * the configuration information for the specified WWDG module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg)
+{
+ /* Check the WWDG handle allocation */
+ if (hwwdg == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_WWDG_ALL_INSTANCE(hwwdg->Instance));
+ assert_param(IS_WWDG_PRESCALER(hwwdg->Init.Prescaler));
+ assert_param(IS_WWDG_WINDOW(hwwdg->Init.Window));
+ assert_param(IS_WWDG_COUNTER(hwwdg->Init.Counter));
+ assert_param(IS_WWDG_EWI_MODE(hwwdg->Init.EWIMode));
+
+#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
+ /* Reset Callback pointers */
+ if (hwwdg->EwiCallback == NULL)
+ {
+ hwwdg->EwiCallback = HAL_WWDG_EarlyWakeupCallback;
+ }
+
+ if (hwwdg->MspInitCallback == NULL)
+ {
+ hwwdg->MspInitCallback = HAL_WWDG_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hwwdg->MspInitCallback(hwwdg);
+#else
+ /* Init the low level hardware */
+ HAL_WWDG_MspInit(hwwdg);
+#endif
+
+ /* Set WWDG Counter */
+ WRITE_REG(hwwdg->Instance->CR, (WWDG_CR_WDGA | hwwdg->Init.Counter));
+
+ /* Set WWDG Prescaler and Window */
+ WRITE_REG(hwwdg->Instance->CFR, (hwwdg->Init.EWIMode | hwwdg->Init.Prescaler | hwwdg->Init.Window));
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Initialize the WWDG MSP.
+ * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
+ * the configuration information for the specified WWDG module.
+ * @note When rewriting this function in user file, mechanism may be added
+ * to avoid multiple initialize when HAL_WWDG_Init function is called
+ * again to change parameters.
+ * @retval None
+ */
+__weak void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hwwdg);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_WWDG_MspInit could be implemented in the user file
+ */
+}
+
+
+#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User WWDG Callback
+ * To be used instead of the weak (surcharged) predefined callback
+ * @param hwwdg WWDG handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_WWDG_EWI_CB_ID Early WakeUp Interrupt Callback ID
+ * @arg @ref HAL_WWDG_MSPINIT_CB_ID MspInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_WWDG_RegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID, pWWDG_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ switch (CallbackID)
+ {
+ case HAL_WWDG_EWI_CB_ID:
+ hwwdg->EwiCallback = pCallback;
+ break;
+
+ case HAL_WWDG_MSPINIT_CB_ID:
+ hwwdg->MspInitCallback = pCallback;
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+ }
+
+ return status;
+}
+
+
+/**
+ * @brief Unregister a WWDG Callback
+ * WWDG Callback is redirected to the weak (surcharged) predefined callback
+ * @param hwwdg WWDG handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_WWDG_EWI_CB_ID Early WakeUp Interrupt Callback ID
+ * @arg @ref HAL_WWDG_MSPINIT_CB_ID MspInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_WWDG_UnRegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ switch (CallbackID)
+ {
+ case HAL_WWDG_EWI_CB_ID:
+ hwwdg->EwiCallback = HAL_WWDG_EarlyWakeupCallback;
+ break;
+
+ case HAL_WWDG_MSPINIT_CB_ID:
+ hwwdg->MspInitCallback = HAL_WWDG_MspInit;
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+#endif
+
+/**
+ * @}
+ */
+
+/** @defgroup WWDG_Exported_Functions_Group2 IO operation functions
+ * @brief IO operation functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Refresh the WWDG.
+ (+) Handle WWDG interrupt request and associated function callback.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Refresh the WWDG.
+ * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
+ * the configuration information for the specified WWDG module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg)
+{
+ /* Write to WWDG CR the WWDG Counter value to refresh with */
+ WRITE_REG(hwwdg->Instance->CR, (hwwdg->Init.Counter));
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle WWDG interrupt request.
+ * @note The Early Wakeup Interrupt (EWI) can be used if specific safety operations
+ * or data logging must be performed before the actual reset is generated.
+ * The EWI interrupt is enabled by calling HAL_WWDG_Init function with
+ * EWIMode set to WWDG_EWI_ENABLE.
+ * When the downcounter reaches the value 0x40, and EWI interrupt is
+ * generated and the corresponding Interrupt Service Routine (ISR) can
+ * be used to trigger specific actions (such as communications or data
+ * logging), before resetting the device.
+ * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
+ * the configuration information for the specified WWDG module.
+ * @retval None
+ */
+void HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg)
+{
+ /* Check if Early Wakeup Interrupt is enable */
+ if (__HAL_WWDG_GET_IT_SOURCE(hwwdg, WWDG_IT_EWI) != RESET)
+ {
+ /* Check if WWDG Early Wakeup Interrupt occurred */
+ if (__HAL_WWDG_GET_FLAG(hwwdg, WWDG_FLAG_EWIF) != RESET)
+ {
+ /* Clear the WWDG Early Wakeup flag */
+ __HAL_WWDG_CLEAR_FLAG(hwwdg, WWDG_FLAG_EWIF);
+
+#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
+ /* Early Wakeup registered callback */
+ hwwdg->EwiCallback(hwwdg);
+#else
+ /* Early Wakeup callback */
+ HAL_WWDG_EarlyWakeupCallback(hwwdg);
+#endif
+ }
+ }
+}
+
+
+/**
+ * @brief WWDG Early Wakeup callback.
+ * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
+ * the configuration information for the specified WWDG module.
+ * @retval None
+ */
+__weak void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hwwdg);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_WWDG_EarlyWakeupCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_WWDG_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_adc.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_adc.c
new file mode 100644
index 0000000000..59c4b10ede
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_adc.c
@@ -0,0 +1,1080 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_adc.c
+ * @author MCD Application Team
+ * @brief ADC LL module driver
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_adc.h"
+#include "stm32h7xx_ll_bus.h"
+
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (ADC1) || defined (ADC2) || defined (ADC3)
+
+/** @addtogroup ADC_LL ADC
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup ADC_LL_Private_Constants
+ * @{
+ */
+
+/* Definitions of ADC hardware constraints delays */
+/* Note: Only ADC peripheral HW delays are defined in ADC LL driver driver, */
+/* not timeout values: */
+/* Timeout values for ADC operations are dependent to device clock */
+/* configuration (system clock versus ADC clock), */
+/* and therefore must be defined in user application. */
+/* Refer to @ref ADC_LL_EC_HW_DELAYS for description of ADC timeout */
+/* values definition. */
+/* Note: ADC timeout values are defined here in CPU cycles to be independent */
+/* of device clock setting. */
+/* In user application, ADC timeout values should be defined with */
+/* temporal values, in function of device clock settings. */
+/* Highest ratio CPU clock frequency vs ADC clock frequency: */
+/* - ADC clock from synchronous clock with AHB prescaler 512, */
+/* APB prescaler 16, ADC prescaler 4. */
+/* - ADC clock from asynchronous clock (PLL) with prescaler 1, */
+/* with highest ratio CPU clock frequency vs HSI clock frequency */
+/* Unit: CPU cycles. */
+#define ADC_CLOCK_RATIO_VS_CPU_HIGHEST (512UL * 16UL * 4UL)
+#define ADC_TIMEOUT_DISABLE_CPU_CYCLES (ADC_CLOCK_RATIO_VS_CPU_HIGHEST * 1UL)
+#define ADC_TIMEOUT_STOP_CONVERSION_CPU_CYCLES (ADC_CLOCK_RATIO_VS_CPU_HIGHEST * 1UL)
+
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+
+/** @addtogroup ADC_LL_Private_Macros
+ * @{
+ */
+
+/* Check of parameters for configuration of ADC hierarchical scope: */
+/* common to several ADC instances. */
+#define IS_LL_ADC_COMMON_CLOCK(__CLOCK__) \
+ ( ((__CLOCK__) == LL_ADC_CLOCK_SYNC_PCLK_DIV1) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_SYNC_PCLK_DIV2) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_SYNC_PCLK_DIV4) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV1) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV2) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV4) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV6) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV8) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV10) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV12) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV16) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV32) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV64) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV128) \
+ || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV256) \
+ )
+
+/* Check of parameters for configuration of ADC hierarchical scope: */
+/* ADC instance. */
+#define IS_LL_ADC_RESOLUTION(__RESOLUTION__) \
+ ( ((__RESOLUTION__) == LL_ADC_RESOLUTION_16B) \
+ || ((__RESOLUTION__) == LL_ADC_RESOLUTION_14B) \
+ || ((__RESOLUTION__) == LL_ADC_RESOLUTION_12B) \
+ || ((__RESOLUTION__) == LL_ADC_RESOLUTION_10B) \
+ || ((__RESOLUTION__) == LL_ADC_RESOLUTION_8B) \
+ )
+
+#define IS_LL_ADC_LEFT_BIT_SHIFT(__LEFT_BIT_SHIFT__) \
+ ( ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_NONE) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_1) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_2) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_3) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_4) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_5) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_6) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_7) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_8) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_9) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_10) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_11) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_12) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_13) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_14) \
+ || ((__LEFT_BIT_SHIFT__) == LL_ADC_LEFT_BIT_SHIFT_15) \
+ )
+
+#define IS_LL_ADC_LOW_POWER(__LOW_POWER__) \
+ ( ((__LOW_POWER__) == LL_ADC_LP_MODE_NONE) \
+ || ((__LOW_POWER__) == LL_ADC_LP_AUTOWAIT) \
+ )
+
+/* Check of parameters for configuration of ADC hierarchical scope: */
+/* ADC group regular */
+#define IS_LL_ADC_REG_TRIG_SOURCE(__REG_TRIG_SOURCE__) \
+ ( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH1) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH2) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH2) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_TRGO) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_CH4) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_EXTI_LINE11) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO2) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_TRGO) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_TRGO2) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_TRGO) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_TRGO) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM6_TRGO) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM15_TRGO) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_CH4) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_HRTIM_TRG1) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_HRTIM_TRG3) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_LPTIM1_OUT) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_LPTIM2_OUT) \
+ || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_LPTIM3_OUT) \
+ )
+
+#define IS_LL_ADC_REG_CONTINUOUS_MODE(__REG_CONTINUOUS_MODE__) \
+ ( ((__REG_CONTINUOUS_MODE__) == LL_ADC_REG_CONV_SINGLE) \
+ || ((__REG_CONTINUOUS_MODE__) == LL_ADC_REG_CONV_CONTINUOUS) \
+ )
+
+#define IS_LL_ADC_REG_DATA_TRANSFER_MODE(__REG_DATA_TRANSFER_MODE__) \
+ ( ((__REG_DATA_TRANSFER_MODE__) == LL_ADC_REG_DR_TRANSFER) \
+ || ((__REG_DATA_TRANSFER_MODE__) == LL_ADC_REG_DMA_TRANSFER_LIMITED) \
+ || ((__REG_DATA_TRANSFER_MODE__) == LL_ADC_REG_DMA_TRANSFER_UNLIMITED) \
+ || ((__REG_DATA_TRANSFER_MODE__) == LL_ADC_REG_DFSDM_TRANSFER) \
+ )
+
+#define IS_LL_ADC_REG_OVR_DATA_BEHAVIOR(__REG_OVR_DATA_BEHAVIOR__) \
+ ( ((__REG_OVR_DATA_BEHAVIOR__) == LL_ADC_REG_OVR_DATA_PRESERVED) \
+ || ((__REG_OVR_DATA_BEHAVIOR__) == LL_ADC_REG_OVR_DATA_OVERWRITTEN) \
+ )
+
+#define IS_LL_ADC_REG_SEQ_SCAN_LENGTH(__REG_SEQ_SCAN_LENGTH__) \
+ ( ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_DISABLE) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_3RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_4RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_6RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_7RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_8RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_9RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_10RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_11RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_12RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_13RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_14RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_15RANKS) \
+ || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_16RANKS) \
+ )
+
+#define IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(__REG_SEQ_DISCONT_MODE__) \
+ ( ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_DISABLE) \
+ || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_1RANK) \
+ || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_2RANKS) \
+ || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_3RANKS) \
+ || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_4RANKS) \
+ || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_5RANKS) \
+ || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_6RANKS) \
+ || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_7RANKS) \
+ || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_8RANKS) \
+ )
+
+/* Check of parameters for configuration of ADC hierarchical scope: */
+/* ADC group injected */
+#define IS_LL_ADC_INJ_TRIG_SOURCE(__INJ_TRIG_SOURCE__) \
+ ( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_TRGO) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_CH1) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH4) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_TRGO) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_EXTI_LINE15) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH4) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO2) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_TRGO) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_TRGO2) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH3) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_TRGO) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH1) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM6_TRGO) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM15_TRGO) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_HRTIM_TRG2) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_HRTIM_TRG4) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_LPTIM1_OUT) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_LPTIM2_OUT) \
+ || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_LPTIM3_OUT) \
+ )
+
+#define IS_LL_ADC_INJ_TRIG_EXT_EDGE(__INJ_TRIG_EXT_EDGE__) \
+ ( ((__INJ_TRIG_EXT_EDGE__) == LL_ADC_INJ_TRIG_EXT_RISING) \
+ || ((__INJ_TRIG_EXT_EDGE__) == LL_ADC_INJ_TRIG_EXT_FALLING) \
+ || ((__INJ_TRIG_EXT_EDGE__) == LL_ADC_INJ_TRIG_EXT_RISINGFALLING) \
+ )
+
+#define IS_LL_ADC_INJ_TRIG_AUTO(__INJ_TRIG_AUTO__) \
+ ( ((__INJ_TRIG_AUTO__) == LL_ADC_INJ_TRIG_INDEPENDENT) \
+ || ((__INJ_TRIG_AUTO__) == LL_ADC_INJ_TRIG_FROM_GRP_REGULAR) \
+ )
+
+#define IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(__INJ_SEQ_SCAN_LENGTH__) \
+ ( ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_DISABLE) \
+ || ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_2RANKS) \
+ || ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_3RANKS) \
+ || ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_4RANKS) \
+ )
+
+#define IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(__INJ_SEQ_DISCONT_MODE__) \
+ ( ((__INJ_SEQ_DISCONT_MODE__) == LL_ADC_INJ_SEQ_DISCONT_DISABLE) \
+ || ((__INJ_SEQ_DISCONT_MODE__) == LL_ADC_INJ_SEQ_DISCONT_1RANK) \
+ )
+
+/* Check of parameters for configuration of ADC hierarchical scope: */
+/* multimode. */
+#define IS_LL_ADC_MULTI_MODE(__MULTI_MODE__) \
+ ( ((__MULTI_MODE__) == LL_ADC_MULTI_INDEPENDENT) \
+ || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIMULT) \
+ || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTERL) \
+ || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_SIMULT) \
+ || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_ALTERN) \
+ || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_SIM) \
+ || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_ALT) \
+ || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INT_INJ_SIM) \
+ )
+
+#define IS_LL_ADC_MULTI_DMA_TRANSFER(__MULTI_DMA_TRANSFER__) \
+ ( ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_EACH_ADC) \
+ || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_RES_32_10B) \
+ || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_RES_8B) \
+ )
+#define IS_LL_ADC_MULTI_TWOSMP_DELAY(__MULTI_TWOSMP_DELAY__) \
+ ( ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_1CYCLE_5) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_2CYCLES_5) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_3CYCLES_5) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_4CYCLES_5) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_4CYCLES_5_8_BITS) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES_5) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES_5_10_BITS) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES_5) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES_5_12_BITS) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_7CYCLES_5) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_8CYCLES) \
+ || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_9CYCLES) \
+ )
+
+#define IS_LL_ADC_MULTI_MASTER_SLAVE(__MULTI_MASTER_SLAVE__) \
+ ( ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_MASTER) \
+ || ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_SLAVE) \
+ || ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_MASTER_SLAVE) \
+ )
+
+/**
+ * @}
+ */
+
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup ADC_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup ADC_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize registers of all ADC instances belonging to
+ * the same ADC common instance to their default reset values.
+ * @note This function is performing a hard reset, using high level
+ * clock source RCC ADC reset.
+ * Caution: On this STM32 serie, if several ADC instances are available
+ * on the selected device, RCC ADC reset will reset
+ * all ADC instances belonging to the common ADC instance.
+ * To de-initialize only 1 ADC instance, use
+ * function @ref LL_ADC_DeInit().
+ * @param ADCxy_COMMON ADC common instance
+ * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() )
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: ADC common registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_ADC_CommonDeInit(ADC_Common_TypeDef *ADCxy_COMMON)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON));
+
+ if(ADCxy_COMMON == ADC12_COMMON)
+ {
+ /* Force reset of ADC clock (core clock) */
+ LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_ADC12);
+
+ /* Release reset of ADC clock (core clock) */
+ LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_ADC12);
+ }
+ else
+ {
+#if defined (ADC3)
+ /* Force reset of ADC clock (core clock) */
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_ADC3);
+
+ /* Release reset of ADC clock (core clock) */
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_ADC3);
+#endif
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Initialize some features of ADC common parameters
+ * (all ADC instances belonging to the same ADC common instance)
+ * and multimode (for devices with several ADC instances available).
+ * @note The setting of ADC common parameters is conditioned to
+ * ADC instances state:
+ * All ADC instances belonging to the same ADC common instance
+ * must be disabled.
+ * @param ADCxy_COMMON ADC common instance
+ * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() )
+ * @param ADC_CommonInitStruct Pointer to a @ref LL_ADC_CommonInitTypeDef structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: ADC common registers are initialized
+ * - ERROR: ADC common registers are not initialized
+ */
+ErrorStatus LL_ADC_CommonInit(ADC_Common_TypeDef *ADCxy_COMMON, LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON));
+ assert_param(IS_LL_ADC_COMMON_CLOCK(ADC_CommonInitStruct->CommonClock));
+
+ assert_param(IS_LL_ADC_MULTI_MODE(ADC_CommonInitStruct->Multimode));
+ if (ADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT)
+ {
+ assert_param(IS_LL_ADC_MULTI_DMA_TRANSFER(ADC_CommonInitStruct->MultiDMATransfer));
+ assert_param(IS_LL_ADC_MULTI_TWOSMP_DELAY(ADC_CommonInitStruct->MultiTwoSamplingDelay));
+ }
+
+ /* Note: Hardware constraint (refer to description of functions */
+ /* "LL_ADC_SetCommonXXX()" and "LL_ADC_SetMultiXXX()"): */
+ /* On this STM32 serie, setting of these features is conditioned to */
+ /* ADC state: */
+ /* All ADC instances of the ADC common group must be disabled. */
+ if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(ADCxy_COMMON) == 0UL)
+ {
+ /* Configuration of ADC hierarchical scope: */
+ /* - common to several ADC */
+ /* (all ADC instances belonging to the same ADC common instance) */
+ /* - Set ADC clock (conversion clock) */
+ /* - multimode (if several ADC instances available on the */
+ /* selected device) */
+ /* - Set ADC multimode configuration */
+ /* - Set ADC multimode DMA transfer */
+ /* - Set ADC multimode: delay between 2 sampling phases */
+ if (ADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT)
+ {
+ MODIFY_REG(ADCxy_COMMON->CCR,
+ ADC_CCR_CKMODE
+ | ADC_CCR_PRESC
+ | ADC_CCR_DUAL
+ | ADC_CCR_DAMDF
+ | ADC_CCR_DELAY
+ ,
+ ADC_CommonInitStruct->CommonClock
+ | ADC_CommonInitStruct->Multimode
+ | ADC_CommonInitStruct->MultiDMATransfer
+ | ADC_CommonInitStruct->MultiTwoSamplingDelay
+ );
+ }
+ else
+ {
+ MODIFY_REG(ADCxy_COMMON->CCR,
+ ADC_CCR_CKMODE
+ | ADC_CCR_PRESC
+ | ADC_CCR_DUAL
+ | ADC_CCR_DAMDF
+ | ADC_CCR_DELAY
+ ,
+ ADC_CommonInitStruct->CommonClock
+ | LL_ADC_MULTI_INDEPENDENT
+ );
+ }
+ }
+ else
+ {
+ /* Initialization error: One or several ADC instances belonging to */
+ /* the same ADC common instance are not disabled. */
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_ADC_CommonInitTypeDef field to default value.
+ * @param ADC_CommonInitStruct Pointer to a @ref LL_ADC_CommonInitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_ADC_CommonStructInit(LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct)
+{
+ /* Set ADC_CommonInitStruct fields to default values */
+ /* Set fields of ADC common */
+ /* (all ADC instances belonging to the same ADC common instance) */
+ ADC_CommonInitStruct->CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV2;
+
+ /* Set fields of ADC multimode */
+ ADC_CommonInitStruct->Multimode = LL_ADC_MULTI_INDEPENDENT;
+ ADC_CommonInitStruct->MultiDMATransfer = LL_ADC_MULTI_REG_DMA_EACH_ADC;
+ ADC_CommonInitStruct->MultiTwoSamplingDelay = LL_ADC_MULTI_TWOSMP_DELAY_1CYCLE_5;
+}
+
+/**
+ * @brief De-initialize registers of the selected ADC instance
+ * to their default reset values.
+ * @note To reset all ADC instances quickly (perform a hard reset),
+ * use function @ref LL_ADC_CommonDeInit().
+ * @note If this functions returns error status, it means that ADC instance
+ * is in an unknown state.
+ * In this case, perform a hard reset using high level
+ * clock source RCC ADC reset.
+ * Caution: On this STM32 serie, if several ADC instances are available
+ * on the selected device, RCC ADC reset will reset
+ * all ADC instances belonging to the common ADC instance.
+ * Refer to function @ref LL_ADC_CommonDeInit().
+ * @param ADCx ADC instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: ADC registers are de-initialized
+ * - ERROR: ADC registers are not de-initialized
+ */
+ErrorStatus LL_ADC_DeInit(ADC_TypeDef *ADCx)
+{
+ ErrorStatus status = SUCCESS;
+
+ __IO uint32_t timeout_cpu_cycles = 0UL;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(ADCx));
+
+ /* Disable ADC instance if not already disabled. */
+ if (LL_ADC_IsEnabled(ADCx) == 1UL)
+ {
+ /* Set ADC group regular trigger source to SW start to ensure to not */
+ /* have an external trigger event occurring during the conversion stop */
+ /* ADC disable process. */
+ LL_ADC_REG_SetTriggerSource(ADCx, LL_ADC_REG_TRIG_SOFTWARE);
+
+ /* Stop potential ADC conversion on going on ADC group regular. */
+ if (LL_ADC_REG_IsConversionOngoing(ADCx) != 0UL)
+ {
+ if (LL_ADC_REG_IsStopConversionOngoing(ADCx) == 0UL)
+ {
+ LL_ADC_REG_StopConversion(ADCx);
+ }
+ }
+
+ /* Set ADC group injected trigger source to SW start to ensure to not */
+ /* have an external trigger event occurring during the conversion stop */
+ /* ADC disable process. */
+ LL_ADC_INJ_SetTriggerSource(ADCx, LL_ADC_INJ_TRIG_SOFTWARE);
+
+ /* Stop potential ADC conversion on going on ADC group injected. */
+ if (LL_ADC_INJ_IsConversionOngoing(ADCx) != 0UL)
+ {
+ if (LL_ADC_INJ_IsStopConversionOngoing(ADCx) == 0UL)
+ {
+ LL_ADC_INJ_StopConversion(ADCx);
+ }
+ }
+
+ /* Wait for ADC conversions are effectively stopped */
+ timeout_cpu_cycles = ADC_TIMEOUT_STOP_CONVERSION_CPU_CYCLES;
+ while ((LL_ADC_REG_IsStopConversionOngoing(ADCx)
+ | LL_ADC_INJ_IsStopConversionOngoing(ADCx)) == 1UL)
+ {
+ timeout_cpu_cycles--;
+ if (timeout_cpu_cycles == 0UL)
+ {
+ /* Time-out error */
+ status = ERROR;
+ break;
+ }
+ }
+
+ /* Flush group injected contexts queue (register JSQR): */
+ /* Note: Bit JQM must be set to empty the contexts queue (otherwise */
+ /* contexts queue is maintained with the last active context). */
+ LL_ADC_INJ_SetQueueMode(ADCx, LL_ADC_INJ_QUEUE_2CONTEXTS_END_EMPTY);
+
+ /* Disable the ADC instance */
+ LL_ADC_Disable(ADCx);
+
+ /* Wait for ADC instance is effectively disabled */
+ timeout_cpu_cycles = ADC_TIMEOUT_DISABLE_CPU_CYCLES;
+ while (LL_ADC_IsDisableOngoing(ADCx) == 1UL)
+ {
+ timeout_cpu_cycles--;
+ if (timeout_cpu_cycles == 0UL)
+ {
+ /* Time-out error */
+ status = ERROR;
+ break;
+ }
+ }
+ }
+
+ /* Check whether ADC state is compliant with expected state */
+ if (READ_BIT(ADCx->CR,
+ (ADC_CR_JADSTP | ADC_CR_ADSTP | ADC_CR_JADSTART | ADC_CR_ADSTART
+ | ADC_CR_ADDIS | ADC_CR_ADEN)
+ )
+ == 0UL)
+ {
+ /* ========== Reset ADC registers ========== */
+ /* Reset register IER */
+ CLEAR_BIT(ADCx->IER,
+ (LL_ADC_IT_ADRDY
+ | LL_ADC_IT_EOC
+ | LL_ADC_IT_EOS
+ | LL_ADC_IT_OVR
+ | LL_ADC_IT_EOSMP
+ | LL_ADC_IT_JEOC
+ | LL_ADC_IT_JEOS
+ | LL_ADC_IT_JQOVF
+ | LL_ADC_IT_AWD1
+ | LL_ADC_IT_AWD2
+ | LL_ADC_IT_AWD3
+ )
+ );
+
+ /* Reset register ISR */
+ SET_BIT(ADCx->ISR,
+ (LL_ADC_FLAG_ADRDY
+ | LL_ADC_FLAG_EOC
+ | LL_ADC_FLAG_EOS
+ | LL_ADC_FLAG_OVR
+ | LL_ADC_FLAG_EOSMP
+ | LL_ADC_FLAG_JEOC
+ | LL_ADC_FLAG_JEOS
+ | LL_ADC_FLAG_JQOVF
+ | LL_ADC_FLAG_AWD1
+ | LL_ADC_FLAG_AWD2
+ | LL_ADC_FLAG_AWD3
+ )
+ );
+
+ /* Reset register CR */
+ /* - Bits ADC_CR_JADSTP, ADC_CR_ADSTP, ADC_CR_JADSTART, ADC_CR_ADSTART, */
+ /* ADC_CR_ADCAL, ADC_CR_ADDIS, ADC_CR_ADEN are in */
+ /* access mode "read-set": no direct reset applicable. */
+ /* - Reset Calibration mode to default setting (single ended). */
+ /* - Disable ADC internal voltage regulator. */
+ /* - Enable ADC deep power down. */
+ /* Note: ADC internal voltage regulator disable and ADC deep power */
+ /* down enable are conditioned to ADC state disabled: */
+ /* already done above. */
+ CLEAR_BIT(ADCx->CR, ADC_CR_ADVREGEN | ADC_CR_ADCALDIF);
+ SET_BIT(ADCx->CR, ADC_CR_DEEPPWD);
+
+ /* Reset register CFGR */
+ CLEAR_BIT(ADCx->CFGR,
+ ( ADC_CFGR_AWD1CH | ADC_CFGR_JAUTO | ADC_CFGR_JAWD1EN
+ | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL | ADC_CFGR_JQM
+ | ADC_CFGR_JDISCEN | ADC_CFGR_DISCNUM | ADC_CFGR_DISCEN
+ | ADC_CFGR_AUTDLY | ADC_CFGR_CONT | ADC_CFGR_OVRMOD
+ | ADC_CFGR_EXTEN | ADC_CFGR_EXTSEL | ADC_CFGR_RES
+ | ADC_CFGR_DMNGT )
+ );
+
+ SET_BIT(ADCx->CFGR, ADC_CFGR_JQDIS);
+
+ /* Reset register CFGR2 */
+ CLEAR_BIT(ADCx->CFGR2,
+ ( ADC_CFGR2_LSHIFT | ADC_CFGR2_OVSR | ADC_CFGR2_RSHIFT1
+ | ADC_CFGR2_RSHIFT4 | ADC_CFGR2_RSHIFT3 | ADC_CFGR2_RSHIFT2
+ | ADC_CFGR2_RSHIFT1 | ADC_CFGR2_ROVSM | ADC_CFGR2_TROVS
+ | ADC_CFGR2_OVSS | ADC_CFGR2_JOVSE | ADC_CFGR2_ROVSE)
+ );
+
+ /* Reset register SMPR1 */
+ CLEAR_BIT(ADCx->SMPR1,
+ (ADC_SMPR1_SMP9 | ADC_SMPR1_SMP8 | ADC_SMPR1_SMP7
+ | ADC_SMPR1_SMP6 | ADC_SMPR1_SMP5 | ADC_SMPR1_SMP4
+ | ADC_SMPR1_SMP3 | ADC_SMPR1_SMP2 | ADC_SMPR1_SMP1)
+ );
+
+ /* Reset register SMPR2 */
+ CLEAR_BIT(ADCx->SMPR2,
+ (ADC_SMPR2_SMP19 | ADC_SMPR2_SMP18 | ADC_SMPR2_SMP17
+ | ADC_SMPR2_SMP16 | ADC_SMPR2_SMP15 | ADC_SMPR2_SMP14
+ | ADC_SMPR2_SMP13 | ADC_SMPR2_SMP12 | ADC_SMPR2_SMP11
+ | ADC_SMPR2_SMP10)
+ );
+
+ /* Reset register TR1 */
+ CLEAR_BIT(ADCx->LTR1, ADC_LTR_LT);
+ SET_BIT(ADCx->HTR1, ADC_HTR_HT);
+
+ CLEAR_BIT(ADCx->LTR2, ADC_LTR_LT);
+ SET_BIT(ADCx->HTR2, ADC_HTR_HT);
+ CLEAR_BIT(ADCx->LTR3, ADC_LTR_LT);
+ SET_BIT(ADCx->HTR3, ADC_HTR_HT);
+
+ /* Reset register SQR1 */
+ CLEAR_BIT(ADCx->SQR1,
+ (ADC_SQR1_SQ4 | ADC_SQR1_SQ3 | ADC_SQR1_SQ2
+ | ADC_SQR1_SQ1 | ADC_SQR1_L)
+ );
+
+ /* Reset register SQR2 */
+ CLEAR_BIT(ADCx->SQR2,
+ (ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7
+ | ADC_SQR2_SQ6 | ADC_SQR2_SQ5)
+ );
+
+ /* Reset register SQR3 */
+ CLEAR_BIT(ADCx->SQR3,
+ (ADC_SQR3_SQ14 | ADC_SQR3_SQ13 | ADC_SQR3_SQ12
+ | ADC_SQR3_SQ11 | ADC_SQR3_SQ10)
+ );
+
+ /* Reset register SQR4 */
+ CLEAR_BIT(ADCx->SQR4, ADC_SQR4_SQ16 | ADC_SQR4_SQ15);
+
+ /* Reset register JSQR */
+ CLEAR_BIT(ADCx->JSQR,
+ (ADC_JSQR_JL
+ | ADC_JSQR_JEXTSEL | ADC_JSQR_JEXTEN
+ | ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3
+ | ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1)
+ );
+
+ /* Reset register DR */
+ /* Note: bits in access mode read only, no direct reset applicable */
+
+ /* Reset register OFR1 */
+ CLEAR_BIT(ADCx->OFR1, ADC_OFR1_OFFSET1 | ADC_OFR1_OFFSET1_CH | ADC_OFR1_SSATE);
+ /* Reset register OFR2 */
+ CLEAR_BIT(ADCx->OFR2, ADC_OFR2_OFFSET2 | ADC_OFR2_OFFSET2_CH | ADC_OFR2_SSATE);
+ /* Reset register OFR3 */
+ CLEAR_BIT(ADCx->OFR3, ADC_OFR3_OFFSET3 | ADC_OFR3_OFFSET3_CH | ADC_OFR3_SSATE);
+ /* Reset register OFR4 */
+ CLEAR_BIT(ADCx->OFR4, ADC_OFR4_OFFSET4 | ADC_OFR4_OFFSET4_CH | ADC_OFR4_SSATE);
+
+ /* Reset registers JDR1, JDR2, JDR3, JDR4 */
+ /* Note: bits in access mode read only, no direct reset applicable */
+
+ /* Reset register AWD2CR */
+ CLEAR_BIT(ADCx->AWD2CR, ADC_AWD2CR_AWD2CH);
+
+ /* Reset register AWD3CR */
+ CLEAR_BIT(ADCx->AWD3CR, ADC_AWD3CR_AWD3CH);
+
+ /* Reset register DIFSEL */
+ CLEAR_BIT(ADCx->DIFSEL, ADC_DIFSEL_DIFSEL);
+
+ /* Reset register CALFACT */
+ CLEAR_BIT(ADCx->CALFACT, ADC_CALFACT_CALFACT_D | ADC_CALFACT_CALFACT_S);
+
+ /* Reset register CALFACT2 */
+ CLEAR_BIT(ADCx->CALFACT2, ADC_CALFACT2_LINCALFACT);
+ }
+ else
+ {
+ /* ADC instance is in an unknown state */
+ /* Need to performing a hard reset of ADC instance, using high level */
+ /* clock source RCC ADC reset. */
+ /* Caution: On this STM32 serie, if several ADC instances are available */
+ /* on the selected device, RCC ADC reset will reset */
+ /* all ADC instances belonging to the common ADC instance. */
+ /* Caution: On this STM32 serie, if several ADC instances are available */
+ /* on the selected device, RCC ADC reset will reset */
+ /* all ADC instances belonging to the common ADC instance. */
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Initialize some features of ADC instance.
+ * @note These parameters have an impact on ADC scope: ADC instance.
+ * Affects both group regular and group injected (availability
+ * of ADC group injected depends on STM32 families).
+ * Refer to corresponding unitary functions into
+ * @ref ADC_LL_EF_Configuration_ADC_Instance .
+ * @note The setting of these parameters by function @ref LL_ADC_Init()
+ * is conditioned to ADC state:
+ * ADC instance must be disabled.
+ * This condition is applied to all ADC features, for efficiency
+ * and compatibility over all STM32 families. However, the different
+ * features can be set under different ADC state conditions
+ * (setting possible with ADC enabled without conversion on going,
+ * ADC enabled with conversion on going, ...)
+ * Each feature can be updated afterwards with a unitary function
+ * and potentially with ADC in a different state than disabled,
+ * refer to description of each function for setting
+ * conditioned to ADC state.
+ * @note After using this function, some other features must be configured
+ * using LL unitary functions.
+ * The minimum configuration remaining to be done is:
+ * - Set ADC group regular or group injected sequencer:
+ * map channel on the selected sequencer rank.
+ * Refer to function @ref LL_ADC_REG_SetSequencerRanks().
+ * - Set ADC channel sampling time
+ * Refer to function LL_ADC_SetChannelSamplingTime();
+ * @param ADCx ADC instance
+ * @param ADC_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: ADC registers are initialized
+ * - ERROR: ADC registers are not initialized
+ */
+ErrorStatus LL_ADC_Init(ADC_TypeDef *ADCx, LL_ADC_InitTypeDef *ADC_InitStruct)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(ADCx));
+
+ assert_param(IS_LL_ADC_RESOLUTION(ADC_InitStruct->Resolution));
+ assert_param(IS_LL_ADC_LEFT_BIT_SHIFT(ADC_InitStruct->LeftBitShift));
+ assert_param(IS_LL_ADC_LOW_POWER(ADC_InitStruct->LowPowerMode));
+
+ /* Note: Hardware constraint (refer to description of this function): */
+ /* ADC instance must be disabled. */
+ if (LL_ADC_IsEnabled(ADCx) == 0UL)
+ {
+ /* Configuration of ADC hierarchical scope: */
+ /* - ADC instance */
+ /* - Set ADC data resolution */
+ /* - Set ADC conversion data alignment */
+ /* - Set ADC low power mode */
+ MODIFY_REG(ADCx->CFGR,
+ ADC_CFGR_RES
+ | ADC_CFGR_AUTDLY
+ ,
+ ADC_InitStruct->Resolution
+ | ADC_InitStruct->LowPowerMode
+ );
+
+ MODIFY_REG(ADCx->CFGR2, ADC_CFGR2_LSHIFT, ADC_InitStruct->LeftBitShift);
+ }
+ else
+ {
+ /* Initialization error: ADC instance is not disabled. */
+ status = ERROR;
+ }
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_ADC_InitTypeDef field to default value.
+ * @param ADC_InitStruct Pointer to a @ref LL_ADC_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_ADC_StructInit(LL_ADC_InitTypeDef *ADC_InitStruct)
+{
+ /* Set ADC_InitStruct fields to default values */
+ /* Set fields of ADC instance */
+ ADC_InitStruct->Resolution = LL_ADC_RESOLUTION_16B;
+ ADC_InitStruct->LeftBitShift = LL_ADC_LEFT_BIT_SHIFT_NONE;
+ ADC_InitStruct->LowPowerMode = LL_ADC_LP_MODE_NONE;
+
+}
+
+/**
+ * @brief Initialize some features of ADC group regular.
+ * @note These parameters have an impact on ADC scope: ADC group regular.
+ * Refer to corresponding unitary functions into
+ * @ref ADC_LL_EF_Configuration_ADC_Group_Regular
+ * (functions with prefix "REG").
+ * @note The setting of these parameters by function @ref LL_ADC_Init()
+ * is conditioned to ADC state:
+ * ADC instance must be disabled.
+ * This condition is applied to all ADC features, for efficiency
+ * and compatibility over all STM32 families. However, the different
+ * features can be set under different ADC state conditions
+ * (setting possible with ADC enabled without conversion on going,
+ * ADC enabled with conversion on going, ...)
+ * Each feature can be updated afterwards with a unitary function
+ * and potentially with ADC in a different state than disabled,
+ * refer to description of each function for setting
+ * conditioned to ADC state.
+ * @note After using this function, other features must be configured
+ * using LL unitary functions.
+ * The minimum configuration remaining to be done is:
+ * - Set ADC group regular or group injected sequencer:
+ * map channel on the selected sequencer rank.
+ * Refer to function @ref LL_ADC_REG_SetSequencerRanks().
+ * - Set ADC channel sampling time
+ * Refer to function LL_ADC_SetChannelSamplingTime();
+ * @param ADCx ADC instance
+ * @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: ADC registers are initialized
+ * - ERROR: ADC registers are not initialized
+ */
+ErrorStatus LL_ADC_REG_Init(ADC_TypeDef *ADCx, LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(ADCx));
+ assert_param(IS_LL_ADC_REG_TRIG_SOURCE(ADC_REG_InitStruct->TriggerSource));
+ assert_param(IS_LL_ADC_REG_SEQ_SCAN_LENGTH(ADC_REG_InitStruct->SequencerLength));
+ if (ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
+ {
+ assert_param(IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(ADC_REG_InitStruct->SequencerDiscont));
+ }
+ assert_param(IS_LL_ADC_REG_CONTINUOUS_MODE(ADC_REG_InitStruct->ContinuousMode));
+ assert_param(IS_LL_ADC_REG_DATA_TRANSFER_MODE(ADC_REG_InitStruct->DataTransferMode));
+ assert_param(IS_LL_ADC_REG_OVR_DATA_BEHAVIOR(ADC_REG_InitStruct->Overrun));
+
+ /* Note: Hardware constraint (refer to description of this function): */
+ /* ADC instance must be disabled. */
+ if (LL_ADC_IsEnabled(ADCx) == 0UL)
+ {
+ /* Configuration of ADC hierarchical scope: */
+ /* - ADC group regular */
+ /* - Set ADC group regular trigger source */
+ /* - Set ADC group regular sequencer length */
+ /* - Set ADC group regular sequencer discontinuous mode */
+ /* - Set ADC group regular continuous mode */
+ /* - Set ADC group regular conversion data transfer: no transfer or */
+ /* transfer by DMA, and DMA requests mode */
+ /* - Set ADC group regular overrun behavior */
+ /* Note: On this STM32 serie, ADC trigger edge is set to value 0x0 by */
+ /* setting of trigger source to SW start. */
+ if (ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
+ {
+ MODIFY_REG(ADCx->CFGR,
+ ADC_CFGR_EXTSEL
+ | ADC_CFGR_EXTEN
+ | ADC_CFGR_DISCEN
+ | ADC_CFGR_DISCNUM
+ | ADC_CFGR_CONT
+ | ADC_CFGR_DMNGT
+ | ADC_CFGR_OVRMOD
+ ,
+ ADC_REG_InitStruct->TriggerSource
+ | ADC_REG_InitStruct->SequencerDiscont
+ | ADC_REG_InitStruct->ContinuousMode
+ | ADC_REG_InitStruct->DataTransferMode
+ | ADC_REG_InitStruct->Overrun
+ );
+ }
+ else
+ {
+ MODIFY_REG(ADCx->CFGR,
+ ADC_CFGR_EXTSEL
+ | ADC_CFGR_EXTEN
+ | ADC_CFGR_DISCEN
+ | ADC_CFGR_DISCNUM
+ | ADC_CFGR_CONT
+ | ADC_CFGR_DMNGT
+ | ADC_CFGR_OVRMOD
+ ,
+ ADC_REG_InitStruct->TriggerSource
+ | LL_ADC_REG_SEQ_DISCONT_DISABLE
+ | ADC_REG_InitStruct->ContinuousMode
+ | ADC_REG_InitStruct->DataTransferMode
+ | ADC_REG_InitStruct->Overrun
+ );
+ }
+
+ /* Set ADC group regular sequencer length and scan direction */
+ LL_ADC_REG_SetSequencerLength(ADCx, ADC_REG_InitStruct->SequencerLength);
+ }
+ else
+ {
+ /* Initialization error: ADC instance is not disabled. */
+ status = ERROR;
+ }
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_ADC_REG_InitTypeDef field to default value.
+ * @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_ADC_REG_StructInit(LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct)
+{
+ /* Set ADC_REG_InitStruct fields to default values */
+ /* Set fields of ADC group regular */
+ /* Note: On this STM32 serie, ADC trigger edge is set to value 0x0 by */
+ /* setting of trigger source to SW start. */
+ ADC_REG_InitStruct->TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
+ ADC_REG_InitStruct->SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
+ ADC_REG_InitStruct->SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
+ ADC_REG_InitStruct->ContinuousMode = LL_ADC_REG_CONV_SINGLE;
+ ADC_REG_InitStruct->DataTransferMode = LL_ADC_REG_DR_TRANSFER;
+ ADC_REG_InitStruct->Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;
+}
+
+/**
+ * @brief Initialize some features of ADC group injected.
+ * @note These parameters have an impact on ADC scope: ADC group injected.
+ * Refer to corresponding unitary functions into
+ * @ref ADC_LL_EF_Configuration_ADC_Group_Regular
+ * (functions with prefix "INJ").
+ * @note The setting of these parameters by function @ref LL_ADC_Init()
+ * is conditioned to ADC state:
+ * ADC instance must be disabled.
+ * This condition is applied to all ADC features, for efficiency
+ * and compatibility over all STM32 families. However, the different
+ * features can be set under different ADC state conditions
+ * (setting possible with ADC enabled without conversion on going,
+ * ADC enabled with conversion on going, ...)
+ * Each feature can be updated afterwards with a unitary function
+ * and potentially with ADC in a different state than disabled,
+ * refer to description of each function for setting
+ * conditioned to ADC state.
+ * @note After using this function, other features must be configured
+ * using LL unitary functions.
+ * The minimum configuration remaining to be done is:
+ * - Set ADC group injected sequencer:
+ * map channel on the selected sequencer rank.
+ * Refer to function @ref LL_ADC_INJ_SetSequencerRanks().
+ * - Set ADC channel sampling time
+ * Refer to function LL_ADC_SetChannelSamplingTime();
+ * @param ADCx ADC instance
+ * @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: ADC registers are initialized
+ * - ERROR: ADC registers are not initialized
+ */
+ErrorStatus LL_ADC_INJ_Init(ADC_TypeDef *ADCx, LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(ADCx));
+ assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(ADC_INJ_InitStruct->TriggerSource));
+ assert_param(IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(ADC_INJ_InitStruct->SequencerLength));
+ if (ADC_INJ_InitStruct->SequencerLength != LL_ADC_INJ_SEQ_SCAN_DISABLE)
+ {
+ assert_param(IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(ADC_INJ_InitStruct->SequencerDiscont));
+ }
+ assert_param(IS_LL_ADC_INJ_TRIG_AUTO(ADC_INJ_InitStruct->TrigAuto));
+
+ /* Note: Hardware constraint (refer to description of this function): */
+ /* ADC instance must be disabled. */
+ if (LL_ADC_IsEnabled(ADCx) == 0UL)
+ {
+ /* Configuration of ADC hierarchical scope: */
+ /* - ADC group injected */
+ /* - Set ADC group injected trigger source */
+ /* - Set ADC group injected sequencer length */
+ /* - Set ADC group injected sequencer discontinuous mode */
+ /* - Set ADC group injected conversion trigger: independent or */
+ /* from ADC group regular */
+ /* Note: On this STM32 serie, ADC trigger edge is set to value 0x0 by */
+ /* setting of trigger source to SW start. */
+ if (ADC_INJ_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
+ {
+ MODIFY_REG(ADCx->CFGR,
+ ADC_CFGR_JDISCEN
+ | ADC_CFGR_JAUTO
+ ,
+ ADC_INJ_InitStruct->SequencerDiscont
+ | ADC_INJ_InitStruct->TrigAuto
+ );
+ }
+ else
+ {
+ MODIFY_REG(ADCx->CFGR,
+ ADC_CFGR_JDISCEN
+ | ADC_CFGR_JAUTO
+ ,
+ LL_ADC_REG_SEQ_DISCONT_DISABLE
+ | ADC_INJ_InitStruct->TrigAuto
+ );
+ }
+
+ MODIFY_REG(ADCx->JSQR,
+ ADC_JSQR_JEXTSEL
+ | ADC_JSQR_JEXTEN
+ | ADC_JSQR_JL
+ ,
+ ADC_INJ_InitStruct->TriggerSource
+ | ADC_INJ_InitStruct->SequencerLength
+ );
+ }
+ else
+ {
+ /* Initialization error: ADC instance is not disabled. */
+ status = ERROR;
+ }
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_ADC_INJ_InitTypeDef field to default value.
+ * @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_ADC_INJ_StructInit(LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct)
+{
+ /* Set ADC_INJ_InitStruct fields to default values */
+ /* Set fields of ADC group injected */
+ ADC_INJ_InitStruct->TriggerSource = LL_ADC_INJ_TRIG_SOFTWARE;
+ ADC_INJ_InitStruct->SequencerLength = LL_ADC_INJ_SEQ_SCAN_DISABLE;
+ ADC_INJ_InitStruct->SequencerDiscont = LL_ADC_INJ_SEQ_DISCONT_DISABLE;
+ ADC_INJ_InitStruct->TrigAuto = LL_ADC_INJ_TRIG_INDEPENDENT;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* ADC1 || ADC2 || ADC3 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_bdma.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_bdma.c
new file mode 100644
index 0000000000..2a2f4a4a52
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_bdma.c
@@ -0,0 +1,346 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_bdma.c
+ * @author MCD Application Team
+ * @brief BDMA LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_bdma.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (BDMA) || defined (BDMA1) || defined (BDMA2)
+
+/** @addtogroup BDMA_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup BDMA_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_BDMA_DIRECTION(__VALUE__) (((__VALUE__) == LL_BDMA_DIRECTION_PERIPH_TO_MEMORY) || \
+ ((__VALUE__) == LL_BDMA_DIRECTION_MEMORY_TO_PERIPH) || \
+ ((__VALUE__) == LL_BDMA_DIRECTION_MEMORY_TO_MEMORY))
+
+#define IS_LL_BDMA_MODE(__VALUE__) (((__VALUE__) == LL_BDMA_MODE_NORMAL) || \
+ ((__VALUE__) == LL_BDMA_MODE_CIRCULAR))
+
+#define IS_LL_BDMA_PERIPHINCMODE(__VALUE__) (((__VALUE__) == LL_BDMA_PERIPH_INCREMENT) || \
+ ((__VALUE__) == LL_BDMA_PERIPH_NOINCREMENT))
+
+#define IS_LL_BDMA_MEMORYINCMODE(__VALUE__) (((__VALUE__) == LL_BDMA_MEMORY_INCREMENT) || \
+ ((__VALUE__) == LL_BDMA_MEMORY_NOINCREMENT))
+
+#define IS_LL_BDMA_PERIPHDATASIZE(__VALUE__) (((__VALUE__) == LL_BDMA_PDATAALIGN_BYTE) || \
+ ((__VALUE__) == LL_BDMA_PDATAALIGN_HALFWORD) || \
+ ((__VALUE__) == LL_BDMA_PDATAALIGN_WORD))
+
+#define IS_LL_BDMA_MEMORYDATASIZE(__VALUE__) (((__VALUE__) == LL_BDMA_MDATAALIGN_BYTE) || \
+ ((__VALUE__) == LL_BDMA_MDATAALIGN_HALFWORD) || \
+ ((__VALUE__) == LL_BDMA_MDATAALIGN_WORD))
+
+#define IS_LL_BDMA_NBDATA(__VALUE__) ((__VALUE__) <= 0x0000FFFFU)
+
+#if defined(ADC3)
+#define IS_LL_BDMA_PERIPHREQUEST(__VALUE__) ((__VALUE__) <= LL_DMAMUX2_REQ_ADC3)
+#else
+#define IS_LL_BDMA_PERIPHREQUEST(__VALUE__) ((__VALUE__) <= LL_DMAMUX2_REQ_DFSDM2_FLT0)
+#endif /* ADC3 */
+
+#define IS_LL_BDMA_PRIORITY(__VALUE__) (((__VALUE__) == LL_BDMA_PRIORITY_LOW) || \
+ ((__VALUE__) == LL_BDMA_PRIORITY_MEDIUM) || \
+ ((__VALUE__) == LL_BDMA_PRIORITY_HIGH) || \
+ ((__VALUE__) == LL_BDMA_PRIORITY_VERYHIGH))
+
+#define IS_LL_BDMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == BDMA) && \
+ (((CHANNEL) == LL_BDMA_CHANNEL_0) || \
+ ((CHANNEL) == LL_BDMA_CHANNEL_1) || \
+ ((CHANNEL) == LL_BDMA_CHANNEL_2) || \
+ ((CHANNEL) == LL_BDMA_CHANNEL_3) || \
+ ((CHANNEL) == LL_BDMA_CHANNEL_4) || \
+ ((CHANNEL) == LL_BDMA_CHANNEL_5) || \
+ ((CHANNEL) == LL_BDMA_CHANNEL_6) || \
+ ((CHANNEL) == LL_BDMA_CHANNEL_7))))
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup BDMA_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup BDMA_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize the DMA registers to their default reset values.
+ * @param BDMAx BDMAx Instance
+ * @param Channel This parameter can be one of the following values:
+ * @arg @ref LL_BDMA_CHANNEL_0
+ * @arg @ref LL_BDMA_CHANNEL_1
+ * @arg @ref LL_BDMA_CHANNEL_2
+ * @arg @ref LL_BDMA_CHANNEL_3
+ * @arg @ref LL_BDMA_CHANNEL_4
+ * @arg @ref LL_BDMA_CHANNEL_5
+ * @arg @ref LL_BDMA_CHANNEL_6
+ * @arg @ref LL_BDMA_CHANNEL_7
+ * @arg @ref LL_BDMA_CHANNEL_ALL
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: DMA registers are de-initialized
+ * - ERROR: DMA registers are not de-initialized
+ */
+uint32_t LL_BDMA_DeInit(BDMA_TypeDef *BDMAx, uint32_t Channel)
+{
+ BDMA_Channel_TypeDef *tmp ;
+ ErrorStatus status = SUCCESS;
+
+ /* Check the DMA Instance DMAx and Channel parameters */
+ assert_param(IS_LL_BDMA_ALL_CHANNEL_INSTANCE(BDMAx, Channel) || (Channel == LL_BDMA_CHANNEL_ALL));
+
+ if (Channel == LL_BDMA_CHANNEL_ALL)
+ {
+ if (BDMAx == BDMA)
+ {
+ /* Force reset of BDMA clock */
+ LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA1);
+
+ /* Release reset of BDMA clock */
+ LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA1);
+ }
+ else
+ {
+ status = ERROR;
+ }
+ }
+ else
+ {
+ tmp = (BDMA_Channel_TypeDef *)(__LL_BDMA_GET_CHANNEL_INSTANCE(BDMAx, Channel));
+
+ /* Disable the selected DMAx_Channely */
+ CLEAR_BIT(tmp->CCR, BDMA_CCR_EN);
+
+ /* Reset DMAx_Channely control register */
+ LL_BDMA_WriteReg(tmp, CCR, 0U);
+
+ /* Reset DMAx_Channely remaining bytes register */
+ LL_BDMA_WriteReg(tmp, CNDTR, 0U);
+
+ /* Reset DMAx_Channely peripheral address register */
+ LL_BDMA_WriteReg(tmp, CPAR, 0U);
+
+ /* Reset DMAx_Channely memory 0 address register */
+ LL_BDMA_WriteReg(tmp, CM0AR, 0U);
+
+ /* Reset DMAx_Channely memory 1 address register */
+ LL_BDMA_WriteReg(tmp, CM1AR, 0U);
+
+ /* Reset Request register field for BDMAx Channel */
+ LL_BDMA_SetPeriphRequest(BDMAx, Channel, LL_DMAMUX2_REQ_MEM2MEM);
+
+ if (Channel == LL_BDMA_CHANNEL_0)
+ {
+ /* Reset interrupt pending bits for DMAx Channel0 */
+ LL_BDMA_ClearFlag_GI0(BDMAx);
+ }
+ else if (Channel == LL_BDMA_CHANNEL_1)
+ {
+ /* Reset interrupt pending bits for DMAx Channel1 */
+ LL_BDMA_ClearFlag_GI1(BDMAx);
+ }
+ else if (Channel == LL_BDMA_CHANNEL_2)
+ {
+ /* Reset interrupt pending bits for DMAx Channel2 */
+ LL_BDMA_ClearFlag_GI2(BDMAx);
+ }
+ else if (Channel == LL_BDMA_CHANNEL_3)
+ {
+ /* Reset interrupt pending bits for DMAx Channel3 */
+ LL_BDMA_ClearFlag_GI3(BDMAx);
+ }
+ else if (Channel == LL_BDMA_CHANNEL_4)
+ {
+ /* Reset interrupt pending bits for DMAx Channel4 */
+ LL_BDMA_ClearFlag_GI4(BDMAx);
+ }
+ else if (Channel == LL_BDMA_CHANNEL_5)
+ {
+ /* Reset interrupt pending bits for DMAx Channel5 */
+ LL_BDMA_ClearFlag_GI5(BDMAx);
+ }
+
+ else if (Channel == LL_BDMA_CHANNEL_6)
+ {
+ /* Reset interrupt pending bits for DMAx Channel6 */
+ LL_BDMA_ClearFlag_GI6(BDMAx);
+ }
+ else if (Channel == LL_BDMA_CHANNEL_7)
+ {
+ /* Reset interrupt pending bits for DMAx Channel7 */
+ LL_BDMA_ClearFlag_GI7(BDMAx);
+ }
+ else
+ {
+ status = ERROR;
+ }
+ }
+
+ return (uint32_t)status;
+}
+
+/**
+ * @brief Initialize the BDMA registers according to the specified parameters in BDMA_InitStruct.
+ * @note To convert BDMAx_Channely Instance to BDMAx Instance and Channely, use helper macros :
+ * @arg @ref __LL_BDMA_GET_INSTANCE
+ * @arg @ref __LL_BDMA_GET_CHANNEL
+ * @param BDMAx BDMAx Instance
+ * @param Channel This parameter can be one of the following values:
+ * @arg @ref LL_BDMA_CHANNEL_0
+ * @arg @ref LL_BDMA_CHANNEL_1
+ * @arg @ref LL_BDMA_CHANNEL_2
+ * @arg @ref LL_BDMA_CHANNEL_3
+ * @arg @ref LL_BDMA_CHANNEL_4
+ * @arg @ref LL_BDMA_CHANNEL_5
+ * @arg @ref LL_BDMA_CHANNEL_6
+ * @arg @ref LL_BDMA_CHANNEL_7
+ * @param BDMA_InitStruct pointer to a @ref LL_BDMA_InitTypeDef structure.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: DMA registers are initialized
+ * - ERROR: Not applicable
+ */
+uint32_t LL_BDMA_Init(BDMA_TypeDef *BDMAx, uint32_t Channel, LL_BDMA_InitTypeDef *BDMA_InitStruct)
+{
+ /* Check the DMA Instance DMAx and Channel parameters */
+ assert_param(IS_LL_BDMA_ALL_CHANNEL_INSTANCE(BDMAx, Channel));
+
+ /* Check the DMA parameters from BDMA_InitStruct */
+ assert_param(IS_LL_BDMA_DIRECTION(BDMA_InitStruct->Direction));
+ assert_param(IS_LL_BDMA_MODE(BDMA_InitStruct->Mode));
+ assert_param(IS_LL_BDMA_PERIPHINCMODE(BDMA_InitStruct->PeriphOrM2MSrcIncMode));
+ assert_param(IS_LL_BDMA_MEMORYINCMODE(BDMA_InitStruct->MemoryOrM2MDstIncMode));
+ assert_param(IS_LL_BDMA_PERIPHDATASIZE(BDMA_InitStruct->PeriphOrM2MSrcDataSize));
+ assert_param(IS_LL_BDMA_MEMORYDATASIZE(BDMA_InitStruct->MemoryOrM2MDstDataSize));
+ assert_param(IS_LL_BDMA_NBDATA(BDMA_InitStruct->NbData));
+ assert_param(IS_LL_BDMA_PERIPHREQUEST(BDMA_InitStruct->PeriphRequest));
+ assert_param(IS_LL_BDMA_PRIORITY(BDMA_InitStruct->Priority));
+
+ /*---------------------------- DMAx CCR Configuration ------------------------
+ * Configure DMAx_Channely: data transfer direction, data transfer mode,
+ * peripheral and memory increment mode,
+ * data size alignment and priority level with parameters :
+ * - Direction: BDMA_CCR_DIR and BDMA_CCR_MEM2MEM bits
+ * - Mode: BDMA_CCR_CIRC bit
+ * - PeriphOrM2MSrcIncMode: BDMA_CCR_PINC bit
+ * - MemoryOrM2MDstIncMode: BDMA_CCR_MINC bit
+ * - PeriphOrM2MSrcDataSize: BDMA_CCR_PSIZE[1:0] bits
+ * - MemoryOrM2MDstDataSize: BDMA_CCR_MSIZE[1:0] bits
+ * - Priority: BDMA_CCR_PL[1:0] bits
+ */
+ LL_BDMA_ConfigTransfer(BDMAx, Channel, BDMA_InitStruct->Direction | \
+ BDMA_InitStruct->Mode | \
+ BDMA_InitStruct->PeriphOrM2MSrcIncMode | \
+ BDMA_InitStruct->MemoryOrM2MDstIncMode | \
+ BDMA_InitStruct->PeriphOrM2MSrcDataSize | \
+ BDMA_InitStruct->MemoryOrM2MDstDataSize | \
+ BDMA_InitStruct->Priority);
+
+ /*-------------------------- DMAx CMAR Configuration -------------------------
+ * Configure the memory or destination base address with parameter :
+ * - MemoryOrM2MDstAddress: BDMA_CMAR_MA[31:0] bits
+ */
+ LL_BDMA_SetMemoryAddress(BDMAx, Channel, BDMA_InitStruct->MemoryOrM2MDstAddress);
+
+ /*-------------------------- DMAx CPAR Configuration -------------------------
+ * Configure the peripheral or source base address with parameter :
+ * - PeriphOrM2MSrcAddress: BDMA_CPAR_PA[31:0] bits
+ */
+ LL_BDMA_SetPeriphAddress(BDMAx, Channel, BDMA_InitStruct->PeriphOrM2MSrcAddress);
+
+ /*--------------------------- DMAx CNDTR Configuration -----------------------
+ * Configure the peripheral base address with parameter :
+ * - NbData: BDMA_CNDTR_NDT[15:0] bits
+ */
+ LL_BDMA_SetDataLength(BDMAx, Channel, BDMA_InitStruct->NbData);
+
+ /*--------------------------- DMAMUXx CCR Configuration ----------------------
+ * Configure the DMA request for DMA Channels on DMAMUX Channel x with parameter :
+ * - PeriphRequest: BDMA_CxCR[7:0] bits
+ */
+ LL_BDMA_SetPeriphRequest(BDMAx, Channel, BDMA_InitStruct->PeriphRequest);
+
+ return (uint32_t)SUCCESS;
+}
+
+/**
+ * @brief Set each @ref LL_BDMA_InitTypeDef field to default value.
+ * @param BDMA_InitStruct Pointer to a @ref LL_BDMA_InitTypeDef structure.
+ * @retval None
+ */
+void LL_BDMA_StructInit(LL_BDMA_InitTypeDef *BDMA_InitStruct)
+{
+ /* Set BDMA_InitStruct fields to default values */
+ BDMA_InitStruct->PeriphOrM2MSrcAddress = 0x00000000U;
+ BDMA_InitStruct->MemoryOrM2MDstAddress = 0x00000000U;
+ BDMA_InitStruct->Direction = LL_BDMA_DIRECTION_PERIPH_TO_MEMORY;
+ BDMA_InitStruct->Mode = LL_BDMA_MODE_NORMAL;
+ BDMA_InitStruct->PeriphOrM2MSrcIncMode = LL_BDMA_PERIPH_NOINCREMENT;
+ BDMA_InitStruct->MemoryOrM2MDstIncMode = LL_BDMA_MEMORY_NOINCREMENT;
+ BDMA_InitStruct->PeriphOrM2MSrcDataSize = LL_BDMA_PDATAALIGN_BYTE;
+ BDMA_InitStruct->MemoryOrM2MDstDataSize = LL_BDMA_MDATAALIGN_BYTE;
+ BDMA_InitStruct->NbData = 0x00000000U;
+ BDMA_InitStruct->PeriphRequest = LL_DMAMUX2_REQ_MEM2MEM;
+ BDMA_InitStruct->Priority = LL_BDMA_PRIORITY_LOW;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* BDMA || BDMA1 || BDMA2 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_comp.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_comp.c
new file mode 100644
index 0000000000..a91776e3c5
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_comp.c
@@ -0,0 +1,296 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_comp.c
+ * @author MCD Application Team
+ * @brief COMP LL module driver
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_comp.h"
+
+#ifdef USE_FULL_ASSERT
+ #include "stm32_assert.h"
+#else
+ #define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (COMP1) || defined (COMP2)
+
+/** @addtogroup COMP_LL COMP
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+
+/** @addtogroup COMP_LL_Private_Macros
+ * @{
+ */
+
+/* Check of parameters for configuration of COMP hierarchical scope: */
+/* COMP instance. */
+
+#define IS_LL_COMP_POWER_MODE(__POWER_MODE__) \
+ ( ((__POWER_MODE__) == LL_COMP_POWERMODE_HIGHSPEED) \
+ || ((__POWER_MODE__) == LL_COMP_POWERMODE_MEDIUMSPEED) \
+ || ((__POWER_MODE__) == LL_COMP_POWERMODE_ULTRALOWPOWER) \
+ )
+
+/* Note: On this STM32 serie, comparator input plus parameters are */
+/* the same on all COMP instances. */
+/* However, comparator instance kept as macro parameter for */
+/* compatibility with other STM32 families. */
+#if defined (COMP_CFGRx_INP2SEL)
+#define IS_LL_COMP_INPUT_PLUS(__COMP_INSTANCE__, __INPUT_PLUS__) \
+ ( ((__INPUT_PLUS__) == LL_COMP_INPUT_PLUS_IO1) \
+ || ((__INPUT_PLUS__) == LL_COMP_INPUT_PLUS_IO2) \
+ || ((__INPUT_PLUS__) == LL_COMP_INPUT_PLUS_DAC2_CH1))
+#else
+#define IS_LL_COMP_INPUT_PLUS(__COMP_INSTANCE__, __INPUT_PLUS__) \
+ ( ((__INPUT_PLUS__) == LL_COMP_INPUT_PLUS_IO1) \
+ || ((__INPUT_PLUS__) == LL_COMP_INPUT_PLUS_IO2))
+#endif
+
+/* Note: On this STM32 serie, comparator input minus parameters are */
+/* the same on all COMP instances. */
+/* However, comparator instance kept as macro parameter for */
+/* compatibility with other STM32 families. */
+#if defined (COMP_CFGRx_INMSEL_3)
+#define IS_LL_COMP_INPUT_MINUS(__COMP_INSTANCE__, __INPUT_MINUS__) \
+ ( ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_1_4VREFINT) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_1_2VREFINT) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_3_4VREFINT) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_VREFINT) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_DAC1_CH1) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_DAC1_CH2) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_IO1) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_IO2) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_TPSENS_DAC2CH1) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_VBAT_VDDAP))
+#else
+#define IS_LL_COMP_INPUT_MINUS(__COMP_INSTANCE__, __INPUT_MINUS__) \
+ ( ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_1_4VREFINT) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_1_2VREFINT) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_3_4VREFINT) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_VREFINT) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_DAC1_CH1) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_DAC1_CH2) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_IO1) \
+ || ((__INPUT_MINUS__) == LL_COMP_INPUT_MINUS_IO2))
+#endif
+
+#define IS_LL_COMP_INPUT_HYSTERESIS(__INPUT_HYSTERESIS__) \
+ ( ((__INPUT_HYSTERESIS__) == LL_COMP_HYSTERESIS_NONE) \
+ || ((__INPUT_HYSTERESIS__) == LL_COMP_HYSTERESIS_LOW) \
+ || ((__INPUT_HYSTERESIS__) == LL_COMP_HYSTERESIS_MEDIUM) \
+ || ((__INPUT_HYSTERESIS__) == LL_COMP_HYSTERESIS_HIGH) \
+ )
+
+#define IS_LL_COMP_OUTPUT_POLARITY(__POLARITY__) \
+ ( ((__POLARITY__) == LL_COMP_OUTPUTPOL_NONINVERTED) \
+ || ((__POLARITY__) == LL_COMP_OUTPUTPOL_INVERTED) \
+ )
+
+#define IS_LL_COMP_OUTPUT_BLANKING_SOURCE(__OUTPUT_BLANKING_SOURCE__) \
+ ( ((__OUTPUT_BLANKING_SOURCE__) == LL_COMP_BLANKINGSRC_NONE) \
+ || ((__OUTPUT_BLANKING_SOURCE__) == LL_COMP_BLANKINGSRC_TIM1_OC5) \
+ || ((__OUTPUT_BLANKING_SOURCE__) == LL_COMP_BLANKINGSRC_TIM2_OC3) \
+ || ((__OUTPUT_BLANKING_SOURCE__) == LL_COMP_BLANKINGSRC_TIM3_OC3) \
+ || ((__OUTPUT_BLANKING_SOURCE__) == LL_COMP_BLANKINGSRC_TIM3_OC4) \
+ || ((__OUTPUT_BLANKING_SOURCE__) == LL_COMP_BLANKINGSRC_TIM8_OC5) \
+ || ((__OUTPUT_BLANKING_SOURCE__) == LL_COMP_BLANKINGSRC_TIM15_OC1) \
+ )
+
+/**
+ * @}
+ */
+
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup COMP_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup COMP_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize registers of the selected COMP instance
+ * to their default reset values.
+ * @note If comparator is locked, de-initialization by software is
+ * not possible.
+ * The only way to unlock the comparator is a device hardware reset.
+ * @param COMPx COMP instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: COMP registers are de-initialized
+ * - ERROR: COMP registers are not de-initialized
+ */
+ErrorStatus LL_COMP_DeInit(COMP_TypeDef *COMPx)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_INSTANCE(COMPx));
+
+ /* Note: Hardware constraint (refer to description of this function): */
+ /* COMP instance must not be locked. */
+ if(LL_COMP_IsLocked(COMPx) == 0UL)
+ {
+ LL_COMP_WriteReg((COMPx), CFGR, 0x00000000UL);
+
+ }
+ else
+ {
+ /* Comparator instance is locked: de-initialization by software is */
+ /* not possible. */
+ /* The only way to unlock the comparator is a device hardware reset. */
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Initialize some features of COMP instance.
+ * @note This function configures features of the selected COMP instance.
+ * Some features are also available at scope COMP common instance
+ * (common to several COMP instances).
+ * Refer to functions having argument "COMPxy_COMMON" as parameter.
+ * @param COMPx COMP instance
+ * @param COMP_InitStruct Pointer to a @ref LL_COMP_InitTypeDef structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: COMP registers are initialized
+ * - ERROR: COMP registers are not initialized
+ */
+ErrorStatus LL_COMP_Init(COMP_TypeDef *COMPx, LL_COMP_InitTypeDef *COMP_InitStruct)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_INSTANCE(COMPx));
+ assert_param(IS_LL_COMP_POWER_MODE(COMP_InitStruct->PowerMode));
+ assert_param(IS_LL_COMP_INPUT_PLUS(COMPx, COMP_InitStruct->InputPlus));
+ assert_param(IS_LL_COMP_INPUT_MINUS(COMPx, COMP_InitStruct->InputMinus));
+ assert_param(IS_LL_COMP_INPUT_HYSTERESIS(COMP_InitStruct->InputHysteresis));
+ assert_param(IS_LL_COMP_OUTPUT_POLARITY(COMP_InitStruct->OutputPolarity));
+ assert_param(IS_LL_COMP_OUTPUT_BLANKING_SOURCE(COMP_InitStruct->OutputBlankingSource));
+
+ /* Note: Hardware constraint (refer to description of this function) */
+ /* COMP instance must not be locked. */
+ if(LL_COMP_IsLocked(COMPx) == 0UL)
+ {
+ /* Configuration of comparator instance : */
+ /* - PowerMode */
+ /* - InputPlus */
+ /* - InputMinus */
+ /* - InputHysteresis */
+ /* - OutputPolarity */
+ /* - OutputBlankingSource */
+#if defined (COMP_CFGRx_INP2SEL)
+ MODIFY_REG(COMPx->CFGR,
+ COMP_CFGRx_PWRMODE
+ | COMP_CFGRx_INPSEL
+ | COMP_CFGRx_INP2SEL
+ | COMP_CFGRx_SCALEN
+ | COMP_CFGRx_BRGEN
+ | COMP_CFGRx_INMSEL
+ | COMP_CFGRx_HYST
+ | COMP_CFGRx_POLARITY
+ | COMP_CFGRx_BLANKING
+ ,
+ COMP_InitStruct->PowerMode
+ | COMP_InitStruct->InputPlus
+ | COMP_InitStruct->InputMinus
+ | COMP_InitStruct->InputHysteresis
+ | COMP_InitStruct->OutputPolarity
+ | COMP_InitStruct->OutputBlankingSource
+ );
+#else
+ MODIFY_REG(COMPx->CFGR,
+ COMP_CFGRx_PWRMODE
+ | COMP_CFGRx_INPSEL
+ | COMP_CFGRx_SCALEN
+ | COMP_CFGRx_BRGEN
+ | COMP_CFGRx_INMSEL
+ | COMP_CFGRx_HYST
+ | COMP_CFGRx_POLARITY
+ | COMP_CFGRx_BLANKING
+ ,
+ COMP_InitStruct->PowerMode
+ | COMP_InitStruct->InputPlus
+ | COMP_InitStruct->InputMinus
+ | COMP_InitStruct->InputHysteresis
+ | COMP_InitStruct->OutputPolarity
+ | COMP_InitStruct->OutputBlankingSource
+ );
+#endif
+ }
+ else
+ {
+ /* Initialization error: COMP instance is locked. */
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_COMP_InitTypeDef field to default value.
+ * @param COMP_InitStruct Pointer to a @ref LL_COMP_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_COMP_StructInit(LL_COMP_InitTypeDef *COMP_InitStruct)
+{
+ /* Set COMP_InitStruct fields to default values */
+ COMP_InitStruct->PowerMode = LL_COMP_POWERMODE_ULTRALOWPOWER;
+ COMP_InitStruct->InputPlus = LL_COMP_INPUT_PLUS_IO1;
+ COMP_InitStruct->InputMinus = LL_COMP_INPUT_MINUS_VREFINT;
+ COMP_InitStruct->InputHysteresis = LL_COMP_HYSTERESIS_NONE;
+ COMP_InitStruct->OutputPolarity = LL_COMP_OUTPUTPOL_NONINVERTED;
+ COMP_InitStruct->OutputBlankingSource = LL_COMP_BLANKINGSRC_NONE;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* COMP1 || COMP2 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_crc.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_crc.c
new file mode 100644
index 0000000000..4410896b8c
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_crc.c
@@ -0,0 +1,115 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_crc.c
+ * @author MCD Application Team
+ * @brief CRC LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_crc.h"
+#include "stm32h7xx_ll_bus.h"
+
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (CRC)
+
+/** @addtogroup CRC_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup CRC_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup CRC_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize CRC registers (Registers restored to their default values).
+ * @param CRCx CRC Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: CRC registers are de-initialized
+ * - ERROR: CRC registers are not de-initialized
+ */
+ErrorStatus LL_CRC_DeInit(CRC_TypeDef *CRCx)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_CRC_ALL_INSTANCE(CRCx));
+
+ if (CRCx == CRC)
+ {
+#if defined(LL_AHB4_GRP1_PERIPH_CRC)
+ /* Force CRC reset */
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_CRC);
+
+ /* Release CRC reset */
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_CRC);
+#else
+ /* Force CRC reset */
+ LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_CRC);
+
+ /* Release CRC reset */
+ LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_CRC);
+#endif/*LL_AHB4_GRP1_PERIPH_CRC)*/
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ return (status);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined (CRC) */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_crs.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_crs.c
new file mode 100644
index 0000000000..48dd6f8735
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_crs.c
@@ -0,0 +1,86 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_crs.h
+ * @author MCD Application Team
+ * @brief CRS LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_crs.h"
+#include "stm32h7xx_ll_bus.h"
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined(CRS)
+
+/** @defgroup CRS_LL CRS
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup CRS_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup CRS_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-Initializes CRS peripheral registers to their default reset values.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: CRS registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_CRS_DeInit(void)
+{
+ LL_APB1_GRP2_ForceReset(LL_APB1_GRP2_PERIPH_CRS);
+ LL_APB1_GRP2_ReleaseReset(LL_APB1_GRP2_PERIPH_CRS);
+
+ return SUCCESS;
+}
+
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined(CRS) */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_dac.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_dac.c
new file mode 100644
index 0000000000..dbf3e12d80
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_dac.c
@@ -0,0 +1,349 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_dac.c
+ * @author MCD Application Team
+ * @brief DAC LL module driver
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_dac.h"
+#include "stm32h7xx_ll_bus.h"
+
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined(DAC1) || defined(DAC2)
+
+/** @addtogroup DAC_LL DAC
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+
+/** @addtogroup DAC_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_DAC_CHANNEL(__DAC_CHANNEL__) \
+ ( \
+ ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_1) \
+ || ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_2) \
+ )
+
+#if defined (HRTIM1)
+#define IS_LL_DAC_TRIGGER_SOURCE(__TRIGGER_SOURCE__) \
+ ( ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_SOFTWARE) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM1_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM2_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM4_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM5_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM6_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM7_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM8_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM15_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_HRTIM_TRGO1) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_HRTIM_TRGO2) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_LPTIM1_OUT) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_LPTIM2_OUT) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_EXTI_LINE9) \
+ )
+#elif defined (DAC2)
+#define IS_LL_DAC_TRIGGER_SOURCE(__TRIGGER_SOURCE__) \
+ ( ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_SOFTWARE) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM1_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM2_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM4_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM5_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM6_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM7_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM8_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM15_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_LPTIM1_OUT) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_LPTIM2_OUT) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_EXTI_LINE9) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_LPTIM3_OUT) \
+ )
+#else
+#define IS_LL_DAC_TRIGGER_SOURCE(__TRIGGER_SOURCE__) \
+ ( ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_SOFTWARE) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM1_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM2_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM4_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM5_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM6_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM7_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM8_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM15_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_LPTIM1_OUT) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_LPTIM2_OUT) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_EXTI_LINE9) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM23_TRGO) \
+ || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM24_TRGO) \
+ )
+#endif
+
+#define IS_LL_DAC_WAVE_AUTO_GENER_MODE(__WAVE_AUTO_GENERATION_MODE__) \
+ ( ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NONE) \
+ || ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NOISE) \
+ || ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE) \
+ )
+
+#define IS_LL_DAC_WAVE_AUTO_GENER_CONFIG(__WAVE_AUTO_GENERATION_MODE__, __WAVE_AUTO_GENERATION_CONFIG__) \
+ ( (((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NOISE) \
+ && ( ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BIT0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS1_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS2_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS3_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS4_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS5_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS6_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS7_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS8_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS9_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS10_0) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS11_0)) \
+ ) \
+ ||(((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE) \
+ && ( ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_1) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_3) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_7) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_15) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_31) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_63) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_127) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_255) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_511) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_1023) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_2047) \
+ || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_4095)) \
+ ) \
+ )
+
+#define IS_LL_DAC_OUTPUT_BUFFER(__OUTPUT_BUFFER__) \
+ ( ((__OUTPUT_BUFFER__) == LL_DAC_OUTPUT_BUFFER_ENABLE) \
+ || ((__OUTPUT_BUFFER__) == LL_DAC_OUTPUT_BUFFER_DISABLE) \
+ )
+
+#define IS_LL_DAC_OUTPUT_CONNECTION(__OUTPUT_CONNECTION__) \
+ ( ((__OUTPUT_CONNECTION__) == LL_DAC_OUTPUT_CONNECT_GPIO) \
+ || ((__OUTPUT_CONNECTION__) == LL_DAC_OUTPUT_CONNECT_INTERNAL) \
+ )
+
+#define IS_LL_DAC_OUTPUT_MODE(__OUTPUT_MODE__) \
+ ( ((__OUTPUT_MODE__) == LL_DAC_OUTPUT_MODE_NORMAL) \
+ || ((__OUTPUT_MODE__) == LL_DAC_OUTPUT_MODE_SAMPLE_AND_HOLD) \
+ )
+
+/**
+ * @}
+ */
+
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup DAC_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup DAC_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize registers of the selected DAC instance
+ * to their default reset values.
+ * @param DACx DAC instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: DAC registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_DAC_DeInit(DAC_TypeDef *DACx)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_ALL_INSTANCE(DACx));
+
+ if(DACx == DAC1)
+ {
+ /* Force reset of DAC clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_DAC12);
+
+ /* Release reset of DAC clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_DAC12);
+ }
+#if defined (DAC2)
+ else
+ {
+ /* Force reset of DAC clock */
+ LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_DAC2);
+
+ /* Release reset of DAC clock */
+ LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_DAC2);
+ }
+#endif
+
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Initialize some features of DAC channel.
+ * @note @ref LL_DAC_Init() aims to ease basic configuration of a DAC channel.
+ * Leaving it ready to be enabled and output:
+ * a level by calling one of
+ * @ref LL_DAC_ConvertData12RightAligned
+ * @ref LL_DAC_ConvertData12LeftAligned
+ * @ref LL_DAC_ConvertData8RightAligned
+ * or one of the supported autogenerated wave.
+ * @note This function allows configuration of:
+ * - Output mode
+ * - Trigger
+ * - Wave generation
+ * @note The setting of these parameters by function @ref LL_DAC_Init()
+ * is conditioned to DAC state:
+ * DAC channel must be disabled.
+ * @param DACx DAC instance
+ * @param DAC_Channel This parameter can be one of the following values:
+ * @arg @ref LL_DAC_CHANNEL_1
+ * @arg @ref LL_DAC_CHANNEL_2
+ * @param DAC_InitStruct Pointer to a @ref LL_DAC_InitTypeDef structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: DAC registers are initialized
+ * - ERROR: DAC registers are not initialized
+ */
+ErrorStatus LL_DAC_Init(DAC_TypeDef *DACx, uint32_t DAC_Channel, LL_DAC_InitTypeDef *DAC_InitStruct)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_ALL_INSTANCE(DACx));
+ assert_param(IS_LL_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_LL_DAC_TRIGGER_SOURCE(DAC_InitStruct->TriggerSource));
+ assert_param(IS_LL_DAC_OUTPUT_BUFFER(DAC_InitStruct->OutputBuffer));
+ assert_param(IS_LL_DAC_OUTPUT_CONNECTION(DAC_InitStruct->OutputConnection));
+ assert_param(IS_LL_DAC_OUTPUT_MODE(DAC_InitStruct->OutputMode));
+ assert_param(IS_LL_DAC_WAVE_AUTO_GENER_MODE(DAC_InitStruct->WaveAutoGeneration));
+ if (DAC_InitStruct->WaveAutoGeneration != LL_DAC_WAVE_AUTO_GENERATION_NONE)
+ {
+ assert_param(IS_LL_DAC_WAVE_AUTO_GENER_CONFIG(DAC_InitStruct->WaveAutoGeneration,
+ DAC_InitStruct->WaveAutoGenerationConfig));
+ }
+
+ /* Note: Hardware constraint (refer to description of this function) */
+ /* DAC instance must be disabled. */
+ if (LL_DAC_IsEnabled(DACx, DAC_Channel) == 0UL)
+ {
+ /* Configuration of DAC channel: */
+ /* - TriggerSource */
+ /* - WaveAutoGeneration */
+ /* - OutputBuffer */
+ /* - OutputConnection */
+ /* - OutputMode */
+ if (DAC_InitStruct->WaveAutoGeneration != LL_DAC_WAVE_AUTO_GENERATION_NONE)
+ {
+ MODIFY_REG(DACx->CR,
+ (DAC_CR_TSEL1
+ | DAC_CR_WAVE1
+ | DAC_CR_MAMP1
+ ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
+ ,
+ (DAC_InitStruct->TriggerSource
+ | DAC_InitStruct->WaveAutoGeneration
+ | DAC_InitStruct->WaveAutoGenerationConfig
+ ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
+ );
+ }
+ else
+ {
+ MODIFY_REG(DACx->CR,
+ (DAC_CR_TSEL1
+ | DAC_CR_WAVE1
+ ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
+ ,
+ (DAC_InitStruct->TriggerSource
+ | LL_DAC_WAVE_AUTO_GENERATION_NONE
+ ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
+ );
+ }
+ MODIFY_REG(DACx->MCR,
+ (DAC_MCR_MODE1_1
+ | DAC_MCR_MODE1_0
+ | DAC_MCR_MODE1_2
+ ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
+ ,
+ (DAC_InitStruct->OutputBuffer
+ | DAC_InitStruct->OutputConnection
+ | DAC_InitStruct->OutputMode
+ ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
+ );
+ }
+ else
+ {
+ /* Initialization error: DAC instance is not disabled. */
+ status = ERROR;
+ }
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_DAC_InitTypeDef field to default value.
+ * @param DAC_InitStruct pointer to a @ref LL_DAC_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_DAC_StructInit(LL_DAC_InitTypeDef *DAC_InitStruct)
+{
+ /* Set DAC_InitStruct fields to default values */
+ DAC_InitStruct->TriggerSource = LL_DAC_TRIG_SOFTWARE;
+ DAC_InitStruct->WaveAutoGeneration = LL_DAC_WAVE_AUTO_GENERATION_NONE;
+ /* Note: Parameter discarded if wave auto generation is disabled, */
+ /* set anyway to its default value. */
+ DAC_InitStruct->WaveAutoGenerationConfig = LL_DAC_NOISE_LFSR_UNMASK_BIT0;
+ DAC_InitStruct->OutputBuffer = LL_DAC_OUTPUT_BUFFER_ENABLE;
+ DAC_InitStruct->OutputConnection = LL_DAC_OUTPUT_CONNECT_GPIO;
+ DAC_InitStruct->OutputMode = LL_DAC_OUTPUT_MODE_NORMAL;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* DAC1 || DAC2 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_delayblock.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_delayblock.c
new file mode 100644
index 0000000000..54d8863d73
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_delayblock.c
@@ -0,0 +1,210 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ @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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 ------------------------------------------------------------*/
+#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)*/
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_dma.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_dma.c
new file mode 100644
index 0000000000..51dafc5100
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_dma.c
@@ -0,0 +1,423 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_dma.c
+ * @author MCD Application Team
+ * @brief DMA LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_dma.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (DMA1) || defined (DMA2)
+
+/** @addtogroup DMA_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup DMA_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_DMA_DIRECTION(__VALUE__) (((__VALUE__) == LL_DMA_DIRECTION_PERIPH_TO_MEMORY) || \
+ ((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_PERIPH) || \
+ ((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_MEMORY))
+
+#define IS_LL_DMA_MODE(__VALUE__) (((__VALUE__) == LL_DMA_MODE_NORMAL) || \
+ ((__VALUE__) == LL_DMA_MODE_CIRCULAR) || \
+ ((__VALUE__) == LL_DMA_MODE_PFCTRL))
+
+#define IS_LL_DMA_PERIPHINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_PERIPH_INCREMENT) || \
+ ((__VALUE__) == LL_DMA_PERIPH_NOINCREMENT))
+
+#define IS_LL_DMA_MEMORYINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_MEMORY_INCREMENT) || \
+ ((__VALUE__) == LL_DMA_MEMORY_NOINCREMENT))
+
+#define IS_LL_DMA_PERIPHDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_PDATAALIGN_BYTE) || \
+ ((__VALUE__) == LL_DMA_PDATAALIGN_HALFWORD) || \
+ ((__VALUE__) == LL_DMA_PDATAALIGN_WORD))
+
+#define IS_LL_DMA_MEMORYDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_MDATAALIGN_BYTE) || \
+ ((__VALUE__) == LL_DMA_MDATAALIGN_HALFWORD) || \
+ ((__VALUE__) == LL_DMA_MDATAALIGN_WORD))
+
+#define IS_LL_DMA_NBDATA(__VALUE__) ((__VALUE__) <= 0x0000FFFFU)
+
+#if defined(ADC3)
+#define IS_LL_DMA_REQUEST(REQUEST) (((REQUEST) <= LL_DMAMUX1_REQ_ADC3))
+#else
+#define IS_LL_DMA_REQUEST(REQUEST) (((REQUEST) <= LL_DMAMUX1_REQ_USART10_TX))
+#endif /* ADC3 */
+
+#define IS_LL_DMA_PRIORITY(__VALUE__) (((__VALUE__) == LL_DMA_PRIORITY_LOW) || \
+ ((__VALUE__) == LL_DMA_PRIORITY_MEDIUM) || \
+ ((__VALUE__) == LL_DMA_PRIORITY_HIGH) || \
+ ((__VALUE__) == LL_DMA_PRIORITY_VERYHIGH))
+
+#define IS_LL_DMA_ALL_STREAM_INSTANCE(INSTANCE, STREAM) ((((INSTANCE) == DMA1) && \
+ (((STREAM) == LL_DMA_STREAM_0) || \
+ ((STREAM) == LL_DMA_STREAM_1) || \
+ ((STREAM) == LL_DMA_STREAM_2) || \
+ ((STREAM) == LL_DMA_STREAM_3) || \
+ ((STREAM) == LL_DMA_STREAM_4) || \
+ ((STREAM) == LL_DMA_STREAM_5) || \
+ ((STREAM) == LL_DMA_STREAM_6) || \
+ ((STREAM) == LL_DMA_STREAM_7) || \
+ ((STREAM) == LL_DMA_STREAM_ALL))) || \
+ (((INSTANCE) == DMA2) && \
+ (((STREAM) == LL_DMA_STREAM_0) || \
+ ((STREAM) == LL_DMA_STREAM_1) || \
+ ((STREAM) == LL_DMA_STREAM_2) || \
+ ((STREAM) == LL_DMA_STREAM_3) || \
+ ((STREAM) == LL_DMA_STREAM_4) || \
+ ((STREAM) == LL_DMA_STREAM_5) || \
+ ((STREAM) == LL_DMA_STREAM_6) || \
+ ((STREAM) == LL_DMA_STREAM_7) || \
+ ((STREAM) == LL_DMA_STREAM_ALL))))
+
+#define IS_LL_DMA_FIFO_MODE_STATE(STATE) (((STATE) == LL_DMA_FIFOMODE_DISABLE ) || \
+ ((STATE) == LL_DMA_FIFOMODE_ENABLE))
+
+#define IS_LL_DMA_FIFO_THRESHOLD(THRESHOLD) (((THRESHOLD) == LL_DMA_FIFOTHRESHOLD_1_4) || \
+ ((THRESHOLD) == LL_DMA_FIFOTHRESHOLD_1_2) || \
+ ((THRESHOLD) == LL_DMA_FIFOTHRESHOLD_3_4) || \
+ ((THRESHOLD) == LL_DMA_FIFOTHRESHOLD_FULL))
+
+#define IS_LL_DMA_MEMORY_BURST(BURST) (((BURST) == LL_DMA_MBURST_SINGLE) || \
+ ((BURST) == LL_DMA_MBURST_INC4) || \
+ ((BURST) == LL_DMA_MBURST_INC8) || \
+ ((BURST) == LL_DMA_MBURST_INC16))
+
+#define IS_LL_DMA_PERIPHERAL_BURST(BURST) (((BURST) == LL_DMA_PBURST_SINGLE) || \
+ ((BURST) == LL_DMA_PBURST_INC4) || \
+ ((BURST) == LL_DMA_PBURST_INC8) || \
+ ((BURST) == LL_DMA_PBURST_INC16))
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup DMA_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup DMA_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize the DMA registers to their default reset values.
+ * @param DMAx DMAx Instance
+ * @param Stream This parameter can be one of the following values:
+ * @arg @ref LL_DMA_STREAM_0
+ * @arg @ref LL_DMA_STREAM_1
+ * @arg @ref LL_DMA_STREAM_2
+ * @arg @ref LL_DMA_STREAM_3
+ * @arg @ref LL_DMA_STREAM_4
+ * @arg @ref LL_DMA_STREAM_5
+ * @arg @ref LL_DMA_STREAM_6
+ * @arg @ref LL_DMA_STREAM_7
+ * @arg @ref LL_DMA_STREAM_ALL
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: DMA registers are de-initialized
+ * - ERROR: DMA registers are not de-initialized
+ */
+uint32_t LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Stream)
+{
+ DMA_Stream_TypeDef *tmp;
+ ErrorStatus status = SUCCESS;
+
+ /* Check the DMA Instance DMAx and Stream parameters */
+ assert_param(IS_LL_DMA_ALL_STREAM_INSTANCE(DMAx, Stream));
+
+ if (Stream == LL_DMA_STREAM_ALL)
+ {
+ if (DMAx == DMA1)
+ {
+ /* Force reset of DMA clock */
+ LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA1);
+
+ /* Release reset of DMA clock */
+ LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA1);
+ }
+ else if (DMAx == DMA2)
+ {
+ /* Force reset of DMA clock */
+ LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA2);
+
+ /* Release reset of DMA clock */
+ LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA2);
+ }
+ else
+ {
+ status = ERROR;
+ }
+ }
+ else
+ {
+ /* Disable the selected Stream */
+ LL_DMA_DisableStream(DMAx, Stream);
+
+ /* Get the DMA Stream Instance */
+ tmp = (DMA_Stream_TypeDef *)(__LL_DMA_GET_STREAM_INSTANCE(DMAx, Stream));
+
+ /* Reset DMAx_Streamy configuration register */
+ LL_DMA_WriteReg(tmp, CR, 0U);
+
+ /* Reset DMAx_Streamy remaining bytes register */
+ LL_DMA_WriteReg(tmp, NDTR, 0U);
+
+ /* Reset DMAx_Streamy peripheral address register */
+ LL_DMA_WriteReg(tmp, PAR, 0U);
+
+ /* Reset DMAx_Streamy memory address register */
+ LL_DMA_WriteReg(tmp, M0AR, 0U);
+
+ /* Reset DMAx_Streamy memory address register */
+ LL_DMA_WriteReg(tmp, M1AR, 0U);
+
+ /* Reset DMAx_Streamy FIFO control register */
+ LL_DMA_WriteReg(tmp, FCR, 0x00000021U);
+
+ /* Reset Channel register field for DMAx Stream */
+ LL_DMA_SetPeriphRequest(DMAx, Stream, LL_DMAMUX1_REQ_MEM2MEM);
+
+ if (Stream == LL_DMA_STREAM_0)
+ {
+ /* Reset the Stream0 pending flags */
+ DMAx->LIFCR = 0x0000003FU;
+ }
+ else if (Stream == LL_DMA_STREAM_1)
+ {
+ /* Reset the Stream1 pending flags */
+ DMAx->LIFCR = 0x00000F40U;
+ }
+ else if (Stream == LL_DMA_STREAM_2)
+ {
+ /* Reset the Stream2 pending flags */
+ DMAx->LIFCR = 0x003F0000U;
+ }
+ else if (Stream == LL_DMA_STREAM_3)
+ {
+ /* Reset the Stream3 pending flags */
+ DMAx->LIFCR = 0x0F400000U;
+ }
+ else if (Stream == LL_DMA_STREAM_4)
+ {
+ /* Reset the Stream4 pending flags */
+ DMAx->HIFCR = 0x0000003FU;
+ }
+ else if (Stream == LL_DMA_STREAM_5)
+ {
+ /* Reset the Stream5 pending flags */
+ DMAx->HIFCR = 0x00000F40U;
+ }
+ else if (Stream == LL_DMA_STREAM_6)
+ {
+ /* Reset the Stream6 pending flags */
+ DMAx->HIFCR = 0x003F0000U;
+ }
+ else if (Stream == LL_DMA_STREAM_7)
+ {
+ /* Reset the Stream7 pending flags */
+ DMAx->HIFCR = 0x0F400000U;
+ }
+ else
+ {
+ status = ERROR;
+ }
+ }
+
+ return (uint32_t)status;
+}
+
+/**
+ * @brief Initialize the DMA registers according to the specified parameters in DMA_InitStruct.
+ * @note To convert DMAx_Streamy Instance to DMAx Instance and Streamy, use helper macros :
+ * @arg @ref __LL_DMA_GET_INSTANCE
+ * @arg @ref __LL_DMA_GET_STREAM
+ * @param DMAx DMAx Instance
+ * @param Stream This parameter can be one of the following values:
+ * @arg @ref LL_DMA_STREAM_0
+ * @arg @ref LL_DMA_STREAM_1
+ * @arg @ref LL_DMA_STREAM_2
+ * @arg @ref LL_DMA_STREAM_3
+ * @arg @ref LL_DMA_STREAM_4
+ * @arg @ref LL_DMA_STREAM_5
+ * @arg @ref LL_DMA_STREAM_6
+ * @arg @ref LL_DMA_STREAM_7
+ * @param DMA_InitStruct pointer to a @ref LL_DMA_InitTypeDef structure.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: DMA registers are initialized
+ * - ERROR: Not applicable
+ */
+uint32_t LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Stream, LL_DMA_InitTypeDef *DMA_InitStruct)
+{
+ /* Check the DMA Instance DMAx and Stream parameters */
+ assert_param(IS_LL_DMA_ALL_STREAM_INSTANCE(DMAx, Stream));
+
+ /* Check the DMA parameters from DMA_InitStruct */
+ assert_param(IS_LL_DMA_DIRECTION(DMA_InitStruct->Direction));
+ assert_param(IS_LL_DMA_MODE(DMA_InitStruct->Mode));
+ assert_param(IS_LL_DMA_PERIPHINCMODE(DMA_InitStruct->PeriphOrM2MSrcIncMode));
+ assert_param(IS_LL_DMA_MEMORYINCMODE(DMA_InitStruct->MemoryOrM2MDstIncMode));
+ assert_param(IS_LL_DMA_PERIPHDATASIZE(DMA_InitStruct->PeriphOrM2MSrcDataSize));
+ assert_param(IS_LL_DMA_MEMORYDATASIZE(DMA_InitStruct->MemoryOrM2MDstDataSize));
+ assert_param(IS_LL_DMA_NBDATA(DMA_InitStruct->NbData));
+ assert_param(IS_LL_DMA_REQUEST(DMA_InitStruct->PeriphRequest));
+ assert_param(IS_LL_DMA_PRIORITY(DMA_InitStruct->Priority));
+ assert_param(IS_LL_DMA_FIFO_MODE_STATE(DMA_InitStruct->FIFOMode));
+
+ /* Check the memory burst, peripheral burst and FIFO threshold parameters only
+ when FIFO mode is enabled */
+ if (DMA_InitStruct->FIFOMode != LL_DMA_FIFOMODE_DISABLE)
+ {
+ assert_param(IS_LL_DMA_FIFO_THRESHOLD(DMA_InitStruct->FIFOThreshold));
+ assert_param(IS_LL_DMA_MEMORY_BURST(DMA_InitStruct->MemBurst));
+ assert_param(IS_LL_DMA_PERIPHERAL_BURST(DMA_InitStruct->PeriphBurst));
+ }
+
+ /*---------------------------- DMAx SxCR Configuration ------------------------
+ * Configure DMAx_Streamy: data transfer direction, data transfer mode,
+ * peripheral and memory increment mode,
+ * data size alignment and priority level with parameters :
+ * - Direction: DMA_SxCR_DIR[1:0] bits
+ * - Mode: DMA_SxCR_CIRC bit
+ * - PeriphOrM2MSrcIncMode: DMA_SxCR_PINC bit
+ * - MemoryOrM2MDstIncMode: DMA_SxCR_MINC bit
+ * - PeriphOrM2MSrcDataSize: DMA_SxCR_PSIZE[1:0] bits
+ * - MemoryOrM2MDstDataSize: DMA_SxCR_MSIZE[1:0] bits
+ * - Priority: DMA_SxCR_PL[1:0] bits
+ */
+ LL_DMA_ConfigTransfer(DMAx, Stream, DMA_InitStruct->Direction | \
+ DMA_InitStruct->Mode | \
+ DMA_InitStruct->PeriphOrM2MSrcIncMode | \
+ DMA_InitStruct->MemoryOrM2MDstIncMode | \
+ DMA_InitStruct->PeriphOrM2MSrcDataSize | \
+ DMA_InitStruct->MemoryOrM2MDstDataSize | \
+ DMA_InitStruct->Priority
+ );
+
+ if (DMA_InitStruct->FIFOMode != LL_DMA_FIFOMODE_DISABLE)
+ {
+ /*---------------------------- DMAx SxFCR Configuration ------------------------
+ * Configure DMAx_Streamy: fifo mode and fifo threshold with parameters :
+ * - FIFOMode: DMA_SxFCR_DMDIS bit
+ * - FIFOThreshold: DMA_SxFCR_FTH[1:0] bits
+ */
+ LL_DMA_ConfigFifo(DMAx, Stream, DMA_InitStruct->FIFOMode, DMA_InitStruct->FIFOThreshold);
+
+ /*---------------------------- DMAx SxCR Configuration --------------------------
+ * Configure DMAx_Streamy: memory burst transfer with parameters :
+ * - MemBurst: DMA_SxCR_MBURST[1:0] bits
+ */
+ LL_DMA_SetMemoryBurstxfer(DMAx, Stream, DMA_InitStruct->MemBurst);
+
+ /*---------------------------- DMAx SxCR Configuration --------------------------
+ * Configure DMAx_Streamy: peripheral burst transfer with parameters :
+ * - PeriphBurst: DMA_SxCR_PBURST[1:0] bits
+ */
+ LL_DMA_SetPeriphBurstxfer(DMAx, Stream, DMA_InitStruct->PeriphBurst);
+ }
+
+ /*-------------------------- DMAx SxM0AR Configuration --------------------------
+ * Configure the memory or destination base address with parameter :
+ * - MemoryOrM2MDstAddress: DMA_SxM0AR_M0A[31:0] bits
+ */
+ LL_DMA_SetMemoryAddress(DMAx, Stream, DMA_InitStruct->MemoryOrM2MDstAddress);
+
+ /*-------------------------- DMAx SxPAR Configuration ---------------------------
+ * Configure the peripheral or source base address with parameter :
+ * - PeriphOrM2MSrcAddress: DMA_SxPAR_PA[31:0] bits
+ */
+ LL_DMA_SetPeriphAddress(DMAx, Stream, DMA_InitStruct->PeriphOrM2MSrcAddress);
+
+ /*--------------------------- DMAx SxNDTR Configuration -------------------------
+ * Configure the peripheral base address with parameter :
+ * - NbData: DMA_SxNDT[15:0] bits
+ */
+ LL_DMA_SetDataLength(DMAx, Stream, DMA_InitStruct->NbData);
+
+ /*--------------------------- DMA SxCR_CHSEL Configuration ----------------------
+ * Configure the peripheral base address with parameter :
+ * - PeriphRequest: DMA_SxCR_CHSEL[3:0] bits
+ */
+ LL_DMA_SetPeriphRequest(DMAx, Stream, DMA_InitStruct->PeriphRequest);
+
+ return (uint32_t)SUCCESS;
+}
+
+/**
+ * @brief Set each @ref LL_DMA_InitTypeDef field to default value.
+ * @param DMA_InitStruct Pointer to a @ref LL_DMA_InitTypeDef structure.
+ * @retval None
+ */
+void LL_DMA_StructInit(LL_DMA_InitTypeDef *DMA_InitStruct)
+{
+ /* Set DMA_InitStruct fields to default values */
+ DMA_InitStruct->PeriphOrM2MSrcAddress = 0x00000000U;
+ DMA_InitStruct->MemoryOrM2MDstAddress = 0x00000000U;
+ DMA_InitStruct->Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
+ DMA_InitStruct->Mode = LL_DMA_MODE_NORMAL;
+ DMA_InitStruct->PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
+ DMA_InitStruct->MemoryOrM2MDstIncMode = LL_DMA_MEMORY_NOINCREMENT;
+ DMA_InitStruct->PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
+ DMA_InitStruct->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
+ DMA_InitStruct->NbData = 0x00000000U;
+ DMA_InitStruct->PeriphRequest = LL_DMAMUX1_REQ_MEM2MEM;
+ DMA_InitStruct->Priority = LL_DMA_PRIORITY_LOW;
+ DMA_InitStruct->FIFOMode = LL_DMA_FIFOMODE_DISABLE;
+ DMA_InitStruct->FIFOThreshold = LL_DMA_FIFOTHRESHOLD_1_4;
+ DMA_InitStruct->MemBurst = LL_DMA_MBURST_SINGLE;
+ DMA_InitStruct->PeriphBurst = LL_DMA_PBURST_SINGLE;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* DMA1 || DMA2 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_dma2d.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_dma2d.c
new file mode 100644
index 0000000000..1bbe4d4d27
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_dma2d.c
@@ -0,0 +1,635 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_dma2d.c
+ * @author MCD Application Team
+ * @brief DMA2D LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_dma2d.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (DMA2D)
+
+/** @addtogroup DMA2D_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup DMA2D_LL_Private_Constants DMA2D Private Constants
+ * @{
+ */
+#define LL_DMA2D_COLOR 0xFFU /*!< Maximum output color setting */
+#define LL_DMA2D_NUMBEROFLINES DMA2D_NLR_NL /*!< Maximum number of lines */
+#define LL_DMA2D_NUMBEROFPIXELS (DMA2D_NLR_PL >> DMA2D_NLR_PL_Pos) /*!< Maximum number of pixels per lines */
+#define LL_DMA2D_OFFSET_MAX 0x3FFFU /*!< Maximum output line offset expressed in pixels */
+#define LL_DMA2D_CLUTSIZE_MAX 0xFFU /*!< Maximum CLUT size */
+/**
+ * @}
+ */
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup DMA2D_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_DMA2D_MODE(MODE) (((MODE) == LL_DMA2D_MODE_M2M) || \
+ ((MODE) == LL_DMA2D_MODE_M2M_PFC) || \
+ ((MODE) == LL_DMA2D_MODE_M2M_BLEND) || \
+ ((MODE) == LL_DMA2D_MODE_M2M_BLEND_FIXED_COLOR_FG) || \
+ ((MODE) == LL_DMA2D_MODE_M2M_BLEND_FIXED_COLOR_BG) || \
+ ((MODE) == LL_DMA2D_MODE_R2M))
+
+#define IS_LL_DMA2D_OCMODE(MODE_ARGB) (((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_ARGB8888) || \
+ ((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_RGB888) || \
+ ((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_RGB565) || \
+ ((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_ARGB1555) || \
+ ((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_ARGB4444))
+
+#define IS_LL_DMA2D_GREEN(GREEN) ((GREEN) <= LL_DMA2D_COLOR)
+#define IS_LL_DMA2D_RED(RED) ((RED) <= LL_DMA2D_COLOR)
+#define IS_LL_DMA2D_BLUE(BLUE) ((BLUE) <= LL_DMA2D_COLOR)
+#define IS_LL_DMA2D_ALPHA(ALPHA) ((ALPHA) <= LL_DMA2D_COLOR)
+
+#define IS_LL_DMA2D_OFFSET_MODE(MODE) (((MODE) == LL_DMA2D_LINE_OFFSET_PIXELS) || \
+ ((MODE) == LL_DMA2D_LINE_OFFSET_BYTES))
+
+#define IS_LL_DMA2D_OFFSET(OFFSET) ((OFFSET) <= LL_DMA2D_OFFSET_MAX)
+
+#define IS_LL_DMA2D_LINE(LINES) ((LINES) <= LL_DMA2D_NUMBEROFLINES)
+#define IS_LL_DMA2D_PIXEL(PIXELS) ((PIXELS) <= LL_DMA2D_NUMBEROFPIXELS)
+
+#define IS_LL_DMA2D_SWAP_MODE(MODE) (((MODE) == LL_DMA2D_SWAP_MODE_REGULAR) || \
+ ((MODE) == LL_DMA2D_SWAP_MODE_TWO_BY_TWO))
+
+#define IS_LL_DMA2D_ALPHAINV(ALPHA) (((ALPHA) == LL_DMA2D_ALPHA_REGULAR) || \
+ ((ALPHA) == LL_DMA2D_ALPHA_INVERTED))
+
+#define IS_LL_DMA2D_RBSWAP(RBSWAP) (((RBSWAP) == LL_DMA2D_RB_MODE_REGULAR) || \
+ ((RBSWAP) == LL_DMA2D_RB_MODE_SWAP))
+
+#define IS_LL_DMA2D_LCMODE(MODE_ARGB) (((MODE_ARGB) == LL_DMA2D_INPUT_MODE_ARGB8888) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_RGB888) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_RGB565) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_ARGB1555) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_ARGB4444) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_L8) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_AL44) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_AL88) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_L4) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_A8) || \
+ ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_A4))
+
+#define IS_LL_DMA2D_CLUTCMODE(CLUTCMODE) (((CLUTCMODE) == LL_DMA2D_CLUT_COLOR_MODE_ARGB8888) || \
+ ((CLUTCMODE) == LL_DMA2D_CLUT_COLOR_MODE_RGB888))
+
+#define IS_LL_DMA2D_CLUTSIZE(SIZE) ((SIZE) <= LL_DMA2D_CLUTSIZE_MAX)
+
+#define IS_LL_DMA2D_ALPHAMODE(MODE) (((MODE) == LL_DMA2D_ALPHA_MODE_NO_MODIF) || \
+ ((MODE) == LL_DMA2D_ALPHA_MODE_REPLACE) || \
+ ((MODE) == LL_DMA2D_ALPHA_MODE_COMBINE))
+
+#define IS_LL_DMA2D_CHROMA_SUB_SAMPLING(CSS) (((CSS) == LL_DMA2D_CSS_444) || \
+ ((CSS) == LL_DMA2D_CSS_422) || \
+ ((CSS) == LL_DMA2D_CSS_420))
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup DMA2D_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup DMA2D_LL_EF_Init_Functions Initialization and De-initialization Functions
+ * @{
+ */
+
+/**
+ * @brief De-initialize DMA2D registers (registers restored to their default values).
+ * @param DMA2Dx DMA2D Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: DMA2D registers are de-initialized
+ * - ERROR: DMA2D registers are not de-initialized
+ */
+ErrorStatus LL_DMA2D_DeInit(DMA2D_TypeDef *DMA2Dx)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx));
+
+ if (DMA2Dx == DMA2D)
+ {
+ /* Force reset of DMA2D clock */
+ LL_AHB3_GRP1_ForceReset(LL_AHB3_GRP1_PERIPH_DMA2D);
+
+ /* Release reset of DMA2D clock */
+ LL_AHB3_GRP1_ReleaseReset(LL_AHB3_GRP1_PERIPH_DMA2D);
+
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ return (status);
+}
+
+/**
+ * @brief Initialize DMA2D registers according to the specified parameters in DMA2D_InitStruct.
+ * @note DMA2D transfers must be disabled to set initialization bits in configuration registers,
+ * otherwise ERROR result is returned.
+ * @param DMA2Dx DMA2D Instance
+ * @param DMA2D_InitStruct pointer to a LL_DMA2D_InitTypeDef structure
+ * that contains the configuration information for the specified DMA2D peripheral.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: DMA2D registers are initialized according to DMA2D_InitStruct content
+ * - ERROR: Issue occurred during DMA2D registers initialization
+ */
+ErrorStatus LL_DMA2D_Init(DMA2D_TypeDef *DMA2Dx, LL_DMA2D_InitTypeDef *DMA2D_InitStruct)
+{
+ ErrorStatus status = ERROR;
+ LL_DMA2D_ColorTypeDef DMA2D_ColorStruct;
+ uint32_t tmp, tmp1, tmp2;
+ uint32_t regMask, regValue;
+
+ /* Check the parameters */
+ assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx));
+ assert_param(IS_LL_DMA2D_MODE(DMA2D_InitStruct->Mode));
+ assert_param(IS_LL_DMA2D_OCMODE(DMA2D_InitStruct->ColorMode));
+ assert_param(IS_LL_DMA2D_LINE(DMA2D_InitStruct->NbrOfLines));
+ assert_param(IS_LL_DMA2D_PIXEL(DMA2D_InitStruct->NbrOfPixelsPerLines));
+ assert_param(IS_LL_DMA2D_GREEN(DMA2D_InitStruct->OutputGreen));
+ assert_param(IS_LL_DMA2D_RED(DMA2D_InitStruct->OutputRed));
+ assert_param(IS_LL_DMA2D_BLUE(DMA2D_InitStruct->OutputBlue));
+ assert_param(IS_LL_DMA2D_ALPHA(DMA2D_InitStruct->OutputAlpha));
+ assert_param(IS_LL_DMA2D_SWAP_MODE(DMA2D_InitStruct->OutputSwapMode));
+ assert_param(IS_LL_DMA2D_OFFSET_MODE(DMA2D_InitStruct->LineOffsetMode));
+ assert_param(IS_LL_DMA2D_OFFSET(DMA2D_InitStruct->LineOffset));
+ assert_param(IS_LL_DMA2D_ALPHAINV(DMA2D_InitStruct->AlphaInversionMode));
+ assert_param(IS_LL_DMA2D_RBSWAP(DMA2D_InitStruct->RBSwapMode));
+
+ /* DMA2D transfers must be disabled to configure bits in initialization registers */
+ tmp = LL_DMA2D_IsTransferOngoing(DMA2Dx);
+ tmp1 = LL_DMA2D_FGND_IsEnabledCLUTLoad(DMA2Dx);
+ tmp2 = LL_DMA2D_BGND_IsEnabledCLUTLoad(DMA2Dx);
+ if ((tmp == 0U) && (tmp1 == 0U) && (tmp2 == 0U))
+ {
+ /* DMA2D CR register configuration -------------------------------------------*/
+ MODIFY_REG(DMA2Dx->CR, (DMA2D_CR_MODE | DMA2D_CR_LOM), \
+ (DMA2D_InitStruct->Mode | DMA2D_InitStruct->LineOffsetMode));
+
+ /* DMA2D OPFCCR register configuration ---------------------------------------*/
+ regMask = DMA2D_OPFCCR_CM;
+ regValue = DMA2D_InitStruct->ColorMode;
+
+ regMask |= DMA2D_OPFCCR_SB;
+ regValue |= DMA2D_InitStruct->OutputSwapMode;
+
+ regMask |= (DMA2D_OPFCCR_RBS | DMA2D_OPFCCR_AI);
+ regValue |= (DMA2D_InitStruct->AlphaInversionMode | DMA2D_InitStruct->RBSwapMode);
+
+
+ MODIFY_REG(DMA2Dx->OPFCCR, regMask, regValue);
+
+ /* DMA2D OOR register configuration ------------------------------------------*/
+ LL_DMA2D_SetLineOffset(DMA2Dx, DMA2D_InitStruct->LineOffset);
+
+ /* DMA2D NLR register configuration ------------------------------------------*/
+ LL_DMA2D_ConfigSize(DMA2Dx, DMA2D_InitStruct->NbrOfLines, DMA2D_InitStruct->NbrOfPixelsPerLines);
+
+ /* DMA2D OMAR register configuration ------------------------------------------*/
+ LL_DMA2D_SetOutputMemAddr(DMA2Dx, DMA2D_InitStruct->OutputMemoryAddress);
+
+ /* DMA2D OCOLR register configuration ------------------------------------------*/
+ DMA2D_ColorStruct.ColorMode = DMA2D_InitStruct->ColorMode;
+ DMA2D_ColorStruct.OutputBlue = DMA2D_InitStruct->OutputBlue;
+ DMA2D_ColorStruct.OutputGreen = DMA2D_InitStruct->OutputGreen;
+ DMA2D_ColorStruct.OutputRed = DMA2D_InitStruct->OutputRed;
+ DMA2D_ColorStruct.OutputAlpha = DMA2D_InitStruct->OutputAlpha;
+ LL_DMA2D_ConfigOutputColor(DMA2Dx, &DMA2D_ColorStruct);
+
+ status = SUCCESS;
+ }
+ /* If DMA2D transfers are not disabled, return ERROR */
+
+ return (status);
+}
+
+/**
+ * @brief Set each @ref LL_DMA2D_InitTypeDef field to default value.
+ * @param DMA2D_InitStruct pointer to a @ref LL_DMA2D_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_DMA2D_StructInit(LL_DMA2D_InitTypeDef *DMA2D_InitStruct)
+{
+ /* Set DMA2D_InitStruct fields to default values */
+ DMA2D_InitStruct->Mode = LL_DMA2D_MODE_M2M;
+ DMA2D_InitStruct->ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB8888;
+ DMA2D_InitStruct->NbrOfLines = 0x0U;
+ DMA2D_InitStruct->NbrOfPixelsPerLines = 0x0U;
+ DMA2D_InitStruct->LineOffsetMode = LL_DMA2D_LINE_OFFSET_PIXELS;
+ DMA2D_InitStruct->LineOffset = 0x0U;
+ DMA2D_InitStruct->OutputBlue = 0x0U;
+ DMA2D_InitStruct->OutputGreen = 0x0U;
+ DMA2D_InitStruct->OutputRed = 0x0U;
+ DMA2D_InitStruct->OutputAlpha = 0x0U;
+ DMA2D_InitStruct->OutputMemoryAddress = 0x0U;
+ DMA2D_InitStruct->OutputSwapMode = LL_DMA2D_SWAP_MODE_REGULAR;
+ DMA2D_InitStruct->AlphaInversionMode = LL_DMA2D_ALPHA_REGULAR;
+ DMA2D_InitStruct->RBSwapMode = LL_DMA2D_RB_MODE_REGULAR;
+}
+
+/**
+ * @brief Configure the foreground or background according to the specified parameters
+ * in the LL_DMA2D_LayerCfgTypeDef structure.
+ * @param DMA2Dx DMA2D Instance
+ * @param DMA2D_LayerCfg pointer to a LL_DMA2D_LayerCfgTypeDef structure that contains
+ * the configuration information for the specified layer.
+ * @param LayerIdx DMA2D Layer index.
+ * This parameter can be one of the following values:
+ * 0(background) / 1(foreground)
+ * @retval None
+ */
+void LL_DMA2D_ConfigLayer(DMA2D_TypeDef *DMA2Dx, LL_DMA2D_LayerCfgTypeDef *DMA2D_LayerCfg, uint32_t LayerIdx)
+{
+ /* Check the parameters */
+ assert_param(IS_LL_DMA2D_OFFSET(DMA2D_LayerCfg->LineOffset));
+ assert_param(IS_LL_DMA2D_LCMODE(DMA2D_LayerCfg->ColorMode));
+ assert_param(IS_LL_DMA2D_CLUTCMODE(DMA2D_LayerCfg->CLUTColorMode));
+ assert_param(IS_LL_DMA2D_CLUTSIZE(DMA2D_LayerCfg->CLUTSize));
+ assert_param(IS_LL_DMA2D_ALPHAMODE(DMA2D_LayerCfg->AlphaMode));
+ assert_param(IS_LL_DMA2D_GREEN(DMA2D_LayerCfg->Green));
+ assert_param(IS_LL_DMA2D_RED(DMA2D_LayerCfg->Red));
+ assert_param(IS_LL_DMA2D_BLUE(DMA2D_LayerCfg->Blue));
+ assert_param(IS_LL_DMA2D_ALPHA(DMA2D_LayerCfg->Alpha));
+ assert_param(IS_LL_DMA2D_ALPHAINV(DMA2D_LayerCfg->AlphaInversionMode));
+ assert_param(IS_LL_DMA2D_RBSWAP(DMA2D_LayerCfg->RBSwapMode));
+ assert_param(IS_LL_DMA2D_CHROMA_SUB_SAMPLING(DMA2D_LayerCfg->ChromaSubSampling));
+
+
+ if (LayerIdx == 0U)
+ {
+ /* Configure the background memory address */
+ LL_DMA2D_BGND_SetMemAddr(DMA2Dx, DMA2D_LayerCfg->MemoryAddress);
+
+ /* Configure the background line offset */
+ LL_DMA2D_BGND_SetLineOffset(DMA2Dx, DMA2D_LayerCfg->LineOffset);
+
+ /* Configure the background Alpha value, Alpha mode, RB swap, Alpha inversion
+ CLUT size, CLUT Color mode and Color mode */
+ MODIFY_REG(DMA2Dx->BGPFCCR, \
+ (DMA2D_BGPFCCR_ALPHA | DMA2D_BGPFCCR_RBS | DMA2D_BGPFCCR_AI | DMA2D_BGPFCCR_AM | \
+ DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM | DMA2D_BGPFCCR_CM), \
+ ((DMA2D_LayerCfg->Alpha << DMA2D_BGPFCCR_ALPHA_Pos) | DMA2D_LayerCfg->RBSwapMode | \
+ DMA2D_LayerCfg->AlphaInversionMode | DMA2D_LayerCfg->AlphaMode | \
+ (DMA2D_LayerCfg->CLUTSize << DMA2D_BGPFCCR_CS_Pos) | DMA2D_LayerCfg->CLUTColorMode | \
+ DMA2D_LayerCfg->ColorMode));
+
+ /* Configure the background color */
+ LL_DMA2D_BGND_SetColor(DMA2Dx, DMA2D_LayerCfg->Red, DMA2D_LayerCfg->Green, DMA2D_LayerCfg->Blue);
+
+ /* Configure the background CLUT memory address */
+ LL_DMA2D_BGND_SetCLUTMemAddr(DMA2Dx, DMA2D_LayerCfg->CLUTMemoryAddress);
+ }
+ else
+ {
+ /* Configure the foreground memory address */
+ LL_DMA2D_FGND_SetMemAddr(DMA2Dx, DMA2D_LayerCfg->MemoryAddress);
+
+ /* Configure the foreground line offset */
+ LL_DMA2D_FGND_SetLineOffset(DMA2Dx, DMA2D_LayerCfg->LineOffset);
+
+ /* Configure the foreground Alpha value, Alpha mode, RB swap, Alpha inversion
+ CLUT size, CLUT Color mode and Color mode */
+ MODIFY_REG(DMA2Dx->FGPFCCR, \
+ (DMA2D_FGPFCCR_ALPHA | DMA2D_FGPFCCR_RBS | DMA2D_FGPFCCR_AI | DMA2D_FGPFCCR_CSS | DMA2D_FGPFCCR_AM | \
+ DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM | DMA2D_FGPFCCR_CM), \
+ ((DMA2D_LayerCfg->Alpha << DMA2D_FGPFCCR_ALPHA_Pos) | DMA2D_LayerCfg->RBSwapMode | \
+ DMA2D_LayerCfg->AlphaInversionMode | DMA2D_LayerCfg->ChromaSubSampling | \
+ DMA2D_LayerCfg->AlphaMode | (DMA2D_LayerCfg->CLUTSize << DMA2D_FGPFCCR_CS_Pos) | \
+ DMA2D_LayerCfg->CLUTColorMode | DMA2D_LayerCfg->ColorMode));
+
+ /* Configure the foreground color */
+ LL_DMA2D_FGND_SetColor(DMA2Dx, DMA2D_LayerCfg->Red, DMA2D_LayerCfg->Green, DMA2D_LayerCfg->Blue);
+
+ /* Configure the foreground CLUT memory address */
+ LL_DMA2D_FGND_SetCLUTMemAddr(DMA2Dx, DMA2D_LayerCfg->CLUTMemoryAddress);
+ }
+}
+
+/**
+ * @brief Set each @ref LL_DMA2D_LayerCfgTypeDef field to default value.
+ * @param DMA2D_LayerCfg pointer to a @ref LL_DMA2D_LayerCfgTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_DMA2D_LayerCfgStructInit(LL_DMA2D_LayerCfgTypeDef *DMA2D_LayerCfg)
+{
+ /* Set DMA2D_LayerCfg fields to default values */
+ DMA2D_LayerCfg->MemoryAddress = 0x0U;
+ DMA2D_LayerCfg->ColorMode = LL_DMA2D_INPUT_MODE_ARGB8888;
+ DMA2D_LayerCfg->LineOffset = 0x0U;
+ DMA2D_LayerCfg->CLUTColorMode = LL_DMA2D_CLUT_COLOR_MODE_ARGB8888;
+ DMA2D_LayerCfg->CLUTSize = 0x0U;
+ DMA2D_LayerCfg->AlphaMode = LL_DMA2D_ALPHA_MODE_NO_MODIF;
+ DMA2D_LayerCfg->Alpha = 0x0U;
+ DMA2D_LayerCfg->Blue = 0x0U;
+ DMA2D_LayerCfg->Green = 0x0U;
+ DMA2D_LayerCfg->Red = 0x0U;
+ DMA2D_LayerCfg->CLUTMemoryAddress = 0x0U;
+ DMA2D_LayerCfg->AlphaInversionMode = LL_DMA2D_ALPHA_REGULAR;
+ DMA2D_LayerCfg->RBSwapMode = LL_DMA2D_RB_MODE_REGULAR;
+ DMA2D_LayerCfg->ChromaSubSampling = LL_DMA2D_CSS_444;
+}
+
+/**
+ * @brief Initialize DMA2D output color register according to the specified parameters
+ * in DMA2D_ColorStruct.
+ * @param DMA2Dx DMA2D Instance
+ * @param DMA2D_ColorStruct pointer to a LL_DMA2D_ColorTypeDef structure that contains
+ * the color configuration information for the specified DMA2D peripheral.
+ * @retval None
+ */
+void LL_DMA2D_ConfigOutputColor(DMA2D_TypeDef *DMA2Dx, LL_DMA2D_ColorTypeDef *DMA2D_ColorStruct)
+{
+ uint32_t outgreen;
+ uint32_t outred;
+ uint32_t outalpha;
+
+ /* Check the parameters */
+ assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx));
+ assert_param(IS_LL_DMA2D_OCMODE(DMA2D_ColorStruct->ColorMode));
+ assert_param(IS_LL_DMA2D_GREEN(DMA2D_ColorStruct->OutputGreen));
+ assert_param(IS_LL_DMA2D_RED(DMA2D_ColorStruct->OutputRed));
+ assert_param(IS_LL_DMA2D_BLUE(DMA2D_ColorStruct->OutputBlue));
+ assert_param(IS_LL_DMA2D_ALPHA(DMA2D_ColorStruct->OutputAlpha));
+
+ /* DMA2D OCOLR register configuration ------------------------------------------*/
+ if (DMA2D_ColorStruct->ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888)
+ {
+ outgreen = DMA2D_ColorStruct->OutputGreen << 8U;
+ outred = DMA2D_ColorStruct->OutputRed << 16U;
+ outalpha = DMA2D_ColorStruct->OutputAlpha << 24U;
+ }
+ else if (DMA2D_ColorStruct->ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888)
+ {
+ outgreen = DMA2D_ColorStruct->OutputGreen << 8U;
+ outred = DMA2D_ColorStruct->OutputRed << 16U;
+ outalpha = 0x00000000U;
+ }
+ else if (DMA2D_ColorStruct->ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565)
+ {
+ outgreen = DMA2D_ColorStruct->OutputGreen << 5U;
+ outred = DMA2D_ColorStruct->OutputRed << 11U;
+ outalpha = 0x00000000U;
+ }
+ else if (DMA2D_ColorStruct->ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555)
+ {
+ outgreen = DMA2D_ColorStruct->OutputGreen << 5U;
+ outred = DMA2D_ColorStruct->OutputRed << 10U;
+ outalpha = DMA2D_ColorStruct->OutputAlpha << 15U;
+ }
+ else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */
+ {
+ outgreen = DMA2D_ColorStruct->OutputGreen << 4U;
+ outred = DMA2D_ColorStruct->OutputRed << 8U;
+ outalpha = DMA2D_ColorStruct->OutputAlpha << 12U;
+ }
+ LL_DMA2D_SetOutputColor(DMA2Dx, (outgreen | outred | DMA2D_ColorStruct->OutputBlue | outalpha));
+}
+
+/**
+ * @brief Return DMA2D output Blue color.
+ * @param DMA2Dx DMA2D Instance.
+ * @param ColorMode This parameter can be one of the following values:
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444
+ * @retval Output Blue color value between Min_Data=0 and Max_Data=0xFF
+ */
+uint32_t LL_DMA2D_GetOutputBlueColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode)
+{
+ uint32_t color;
+
+ /* Check the parameters */
+ assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx));
+ assert_param(IS_LL_DMA2D_OCMODE(ColorMode));
+
+ /* DMA2D OCOLR register reading ------------------------------------------*/
+ if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFFU));
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFFU));
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x1FU));
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x1FU));
+ }
+ else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFU));
+ }
+
+ return color;
+}
+
+/**
+ * @brief Return DMA2D output Green color.
+ * @param DMA2Dx DMA2D Instance.
+ * @param ColorMode This parameter can be one of the following values:
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444
+ * @retval Output Green color value between Min_Data=0 and Max_Data=0xFF
+ */
+uint32_t LL_DMA2D_GetOutputGreenColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode)
+{
+ uint32_t color;
+
+ /* Check the parameters */
+ assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx));
+ assert_param(IS_LL_DMA2D_OCMODE(ColorMode));
+
+ /* DMA2D OCOLR register reading ------------------------------------------*/
+ if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF00U) >> 8U);
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF00U) >> 8U);
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x7E0U) >> 5U);
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x3E0U) >> 5U);
+ }
+ else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xF0U) >> 4U);
+ }
+
+ return color;
+}
+
+/**
+ * @brief Return DMA2D output Red color.
+ * @param DMA2Dx DMA2D Instance.
+ * @param ColorMode This parameter can be one of the following values:
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444
+ * @retval Output Red color value between Min_Data=0 and Max_Data=0xFF
+ */
+uint32_t LL_DMA2D_GetOutputRedColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode)
+{
+ uint32_t color;
+
+ /* Check the parameters */
+ assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx));
+ assert_param(IS_LL_DMA2D_OCMODE(ColorMode));
+
+ /* DMA2D OCOLR register reading ------------------------------------------*/
+ if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF0000U) >> 16U);
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF0000U) >> 16U);
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xF800U) >> 11U);
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x7C00U) >> 10U);
+ }
+ else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xF00U) >> 8U);
+ }
+
+ return color;
+}
+
+/**
+ * @brief Return DMA2D output Alpha color.
+ * @param DMA2Dx DMA2D Instance.
+ * @param ColorMode This parameter can be one of the following values:
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555
+ * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444
+ * @retval Output Alpha color value between Min_Data=0 and Max_Data=0xFF
+ */
+uint32_t LL_DMA2D_GetOutputAlphaColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode)
+{
+ uint32_t color;
+
+ /* Check the parameters */
+ assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx));
+ assert_param(IS_LL_DMA2D_OCMODE(ColorMode));
+
+ /* DMA2D OCOLR register reading ------------------------------------------*/
+ if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF000000U) >> 24U);
+ }
+ else if ((ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888) || (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565))
+ {
+ color = 0x0U;
+ }
+ else if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555)
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x8000U) >> 15U);
+ }
+ else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */
+ {
+ color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xF000U) >> 12U);
+ }
+
+ return color;
+}
+
+/**
+ * @brief Configure DMA2D transfer size.
+ * @param DMA2Dx DMA2D Instance
+ * @param NbrOfLines Value between Min_Data=0 and Max_Data=0xFFFF
+ * @param NbrOfPixelsPerLines Value between Min_Data=0 and Max_Data=0x3FFF
+ * @retval None
+ */
+void LL_DMA2D_ConfigSize(DMA2D_TypeDef *DMA2Dx, uint32_t NbrOfLines, uint32_t NbrOfPixelsPerLines)
+{
+ MODIFY_REG(DMA2Dx->NLR, (DMA2D_NLR_PL | DMA2D_NLR_NL), \
+ ((NbrOfPixelsPerLines << DMA2D_NLR_PL_Pos) | NbrOfLines));
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined (DMA2D) */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_exti.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_exti.c
new file mode 100644
index 0000000000..f4c6320dfc
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_exti.c
@@ -0,0 +1,458 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_exti.c
+ * @author MCD Application Team
+ * @brief EXTI LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_exti.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (EXTI)
+
+/** @defgroup EXTI_LL EXTI
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup EXTI_LL_Private_Macros
+ * @{
+ */
+
+#define IS_LL_EXTI_LINE_0_31(__VALUE__) (((__VALUE__) & ~LL_EXTI_LINE_ALL_0_31) == 0x00000000U)
+#define IS_LL_EXTI_LINE_32_63(__VALUE__) (((__VALUE__) & ~LL_EXTI_LINE_ALL_32_63) == 0x00000000U)
+#define IS_LL_EXTI_LINE_64_95(__VALUE__) (((__VALUE__) & ~LL_EXTI_LINE_ALL_64_95) == 0x00000000U)
+
+#define IS_LL_EXTI_MODE(__VALUE__) (((__VALUE__) == LL_EXTI_MODE_IT) \
+ || ((__VALUE__) == LL_EXTI_MODE_EVENT) \
+ || ((__VALUE__) == LL_EXTI_MODE_IT_EVENT))
+
+
+#define IS_LL_EXTI_TRIGGER(__VALUE__) (((__VALUE__) == LL_EXTI_TRIGGER_NONE) \
+ || ((__VALUE__) == LL_EXTI_TRIGGER_RISING) \
+ || ((__VALUE__) == LL_EXTI_TRIGGER_FALLING) \
+ || ((__VALUE__) == LL_EXTI_TRIGGER_RISING_FALLING))
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup EXTI_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup EXTI_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize the EXTI registers to their default reset values.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: EXTI registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_EXTI_DeInit(void)
+{
+ /* Rising Trigger selection register set to default reset values */
+ LL_EXTI_WriteReg(RTSR1, 0x00000000U);
+ LL_EXTI_WriteReg(RTSR2, 0x00000000U);
+ LL_EXTI_WriteReg(RTSR3, 0x00000000U);
+
+ /* Falling Trigger selection register set to default reset values */
+ LL_EXTI_WriteReg(FTSR1, 0x00000000U);
+ LL_EXTI_WriteReg(FTSR2, 0x00000000U);
+ LL_EXTI_WriteReg(FTSR3, 0x00000000U);
+
+ /* Software interrupt event register set to default reset values */
+ LL_EXTI_WriteReg(SWIER1, 0x00000000U);
+ LL_EXTI_WriteReg(SWIER2, 0x00000000U);
+ LL_EXTI_WriteReg(SWIER3, 0x00000000U);
+
+ /* D3 Pending register set to default reset values */
+ LL_EXTI_WriteReg(D3PMR1, 0x00000000U);
+ LL_EXTI_WriteReg(D3PMR2, 0x00000000U);
+ LL_EXTI_WriteReg(D3PMR3, 0x00000000U);
+
+ /* D3 Pending clear selection register low to default reset values */
+ LL_EXTI_WriteReg(D3PCR1L, 0x00000000U);
+ LL_EXTI_WriteReg(D3PCR2L, 0x00000000U);
+ LL_EXTI_WriteReg(D3PCR3L, 0x00000000U);
+
+ /* D3 Pending clear selection register high to default reset values */
+ LL_EXTI_WriteReg(D3PCR1H, 0x00000000U);
+ LL_EXTI_WriteReg(D3PCR2H, 0x00000000U);
+ LL_EXTI_WriteReg(D3PCR3H, 0x00000000U);
+
+ /* Interrupt mask register set to default reset values */
+ LL_EXTI_WriteReg(IMR1, 0x00000000U);
+ LL_EXTI_WriteReg(IMR2, 0x00000000U);
+ LL_EXTI_WriteReg(IMR3, 0x00000000U);
+
+ /* Event mask register set to default reset values */
+ LL_EXTI_WriteReg(EMR1, 0x00000000U);
+ LL_EXTI_WriteReg(EMR2, 0x00000000U);
+ LL_EXTI_WriteReg(EMR3, 0x00000000U);
+
+ /* Clear Pending requests */
+ LL_EXTI_WriteReg(PR1, EXTI_PR1_PR_Msk);
+ LL_EXTI_WriteReg(PR2, EXTI_PR2_PR_Msk);
+ LL_EXTI_WriteReg(PR3, EXTI_PR3_PR_Msk);
+
+#if defined(DUAL_CORE)
+ /* Interrupt mask register set to default reset values for Core 2 (Coretx-M4)*/
+ LL_EXTI_WriteReg(C2IMR1, 0x00000000U);
+ LL_EXTI_WriteReg(C2IMR2, 0x00000000U);
+ LL_EXTI_WriteReg(C2IMR3, 0x00000000U);
+
+ /* Event mask register set to default reset values */
+ LL_EXTI_WriteReg(C2EMR1, 0x00000000U);
+ LL_EXTI_WriteReg(C2EMR2, 0x00000000U);
+ LL_EXTI_WriteReg(C2EMR3, 0x00000000U);
+
+ /* Clear Pending requests */
+ LL_EXTI_WriteReg(C2PR1, EXTI_PR1_PR_Msk);
+ LL_EXTI_WriteReg(C2PR2, EXTI_PR2_PR_Msk);
+ LL_EXTI_WriteReg(C2PR3, EXTI_PR3_PR_Msk);
+
+#endif /* DUAL_CORE*/
+ return SUCCESS;
+}
+
+/**
+ * @brief Initialize the EXTI registers according to the specified parameters in EXTI_InitStruct.
+ * @param EXTI_InitStruct pointer to a @ref LL_EXTI_InitTypeDef structure.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: EXTI registers are initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_EXTI_Init(LL_EXTI_InitTypeDef *EXTI_InitStruct)
+{
+ ErrorStatus status = SUCCESS;
+ /* Check the parameters */
+ assert_param(IS_LL_EXTI_LINE_0_31(EXTI_InitStruct->Line_0_31));
+ assert_param(IS_LL_EXTI_LINE_32_63(EXTI_InitStruct->Line_32_63));
+ assert_param(IS_LL_EXTI_LINE_64_95(EXTI_InitStruct->Line_64_95));
+ assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->LineCommand));
+ assert_param(IS_LL_EXTI_MODE(EXTI_InitStruct->Mode));
+
+ /* ENABLE LineCommand */
+ if (EXTI_InitStruct->LineCommand != DISABLE)
+ {
+ assert_param(IS_LL_EXTI_TRIGGER(EXTI_InitStruct->Trigger));
+
+ /* Configure EXTI Lines in range from 0 to 31 */
+ if (EXTI_InitStruct->Line_0_31 != LL_EXTI_LINE_NONE)
+ {
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_IT) == LL_EXTI_MODE_IT)
+ {
+ /* Enable IT on provided Lines for Cortex-M7*/
+ LL_EXTI_EnableIT_0_31(EXTI_InitStruct->Line_0_31);
+ }
+ else
+ {
+ /* Disable IT on provided Lines for Cortex-M7*/
+ LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
+ }
+
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_EVENT) == LL_EXTI_MODE_EVENT)
+ {
+ /* Enable event on provided Lines for Cortex-M7 */
+ LL_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31);
+ }
+ else
+ {
+ /* Disable event on provided Lines for Cortex-M7 */
+ LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
+ }
+#if defined(DUAL_CORE)
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_C2_IT) == LL_EXTI_MODE_C2_IT)
+ {
+ /* Enable IT on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_EnableIT_0_31 (EXTI_InitStruct->Line_0_31);
+ }
+ else
+ {
+ /* Disable IT on provided Lines for Cortex-M4*/
+ LL_C2_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
+ }
+
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_C2_EVENT) == LL_EXTI_MODE_C2_EVENT)
+ {
+ /* Enable event on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31);
+ }
+ else
+ {
+ /* Disable event on provided Lines for Cortex-M4*/
+ LL_C2_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
+ }
+#endif /* DUAL_CORE */
+
+ if (EXTI_InitStruct->Trigger != LL_EXTI_TRIGGER_NONE)
+ {
+ switch (EXTI_InitStruct->Trigger)
+ {
+ case LL_EXTI_TRIGGER_RISING:
+ /* First Disable Falling Trigger on provided Lines */
+ LL_EXTI_DisableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
+ /* Then Enable Rising Trigger on provided Lines */
+ LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
+ break;
+ case LL_EXTI_TRIGGER_FALLING:
+ /* First Disable Rising Trigger on provided Lines */
+ LL_EXTI_DisableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
+ /* Then Enable Falling Trigger on provided Lines */
+ LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
+ break;
+ case LL_EXTI_TRIGGER_RISING_FALLING:
+ LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
+ LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
+ break;
+ default:
+ status = ERROR;
+ break;
+ }
+ }
+ }
+ /* Configure EXTI Lines in range from 32 to 63 */
+ if (EXTI_InitStruct->Line_32_63 != LL_EXTI_LINE_NONE)
+ {
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_IT) == LL_EXTI_MODE_IT)
+ {
+ /* Enable IT on provided Lines for Cortex-M7*/
+ LL_EXTI_EnableIT_32_63(EXTI_InitStruct->Line_32_63);
+ }
+ else
+ {
+ /* Disable IT on provided Lines for Cortex-M7*/
+ LL_EXTI_DisableIT_32_63(EXTI_InitStruct->Line_32_63);
+ }
+
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_EVENT) == LL_EXTI_MODE_EVENT)
+ {
+ /* Enable event on provided Lines for Cortex-M7 */
+ LL_EXTI_EnableEvent_32_63(EXTI_InitStruct->Line_32_63);
+ }
+ else
+ {
+ /* Disable event on provided Lines for Cortex-M7 */
+ LL_EXTI_DisableEvent_32_63(EXTI_InitStruct->Line_32_63);
+ }
+#if defined(DUAL_CORE)
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_C2_IT) == LL_EXTI_MODE_C2_IT)
+ {
+ /* Enable IT on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_EnableIT_32_63 (EXTI_InitStruct->Line_32_63);
+ }
+ else
+ {
+ /* Disable IT on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_DisableIT_32_63 (EXTI_InitStruct->Line_32_63);
+ }
+
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_C2_EVENT) == LL_EXTI_MODE_C2_EVENT)
+ {
+ /* Enable event on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_EnableEvent_32_63(EXTI_InitStruct->Line_32_63);
+ }
+ else
+ {
+ /* Disable event on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_DisableEvent_32_63(EXTI_InitStruct->Line_32_63);
+ }
+#endif /* DUAL_CORE */
+
+ if (EXTI_InitStruct->Trigger != LL_EXTI_TRIGGER_NONE)
+ {
+ switch (EXTI_InitStruct->Trigger)
+ {
+ case LL_EXTI_TRIGGER_RISING:
+ /* First Disable Falling Trigger on provided Lines */
+ LL_EXTI_DisableFallingTrig_32_63(EXTI_InitStruct->Line_32_63);
+ /* Then Enable IT on provided Lines */
+ LL_EXTI_EnableRisingTrig_32_63(EXTI_InitStruct->Line_32_63);
+ break;
+ case LL_EXTI_TRIGGER_FALLING:
+ /* First Disable Rising Trigger on provided Lines */
+ LL_EXTI_DisableRisingTrig_32_63(EXTI_InitStruct->Line_32_63);
+ /* Then Enable Falling Trigger on provided Lines */
+ LL_EXTI_EnableFallingTrig_32_63(EXTI_InitStruct->Line_32_63);
+ break;
+ case LL_EXTI_TRIGGER_RISING_FALLING:
+ LL_EXTI_EnableRisingTrig_32_63(EXTI_InitStruct->Line_32_63);
+ LL_EXTI_EnableFallingTrig_32_63(EXTI_InitStruct->Line_32_63);
+ break;
+ default:
+ status = ERROR;
+ break;
+ }
+ }
+ }
+ /* Configure EXTI Lines in range from 64 to 95 */
+ if (EXTI_InitStruct->Line_64_95 != LL_EXTI_LINE_NONE)
+ {
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_IT) == LL_EXTI_MODE_IT)
+ {
+ /* Enable IT on provided Lines for Cortex-M7*/
+ LL_EXTI_EnableIT_64_95(EXTI_InitStruct->Line_64_95);
+ }
+ else
+ {
+ /* Disable IT on provided Lines for Cortex-M7*/
+ LL_EXTI_DisableIT_64_95(EXTI_InitStruct->Line_64_95);
+ }
+
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_EVENT) == LL_EXTI_MODE_EVENT)
+ {
+ /* Enable event on provided Lines for Cortex-M7 */
+ LL_EXTI_EnableEvent_64_95(EXTI_InitStruct->Line_64_95);
+ }
+ else
+ {
+ /* Disable event on provided Lines for Cortex-M7 */
+ LL_EXTI_DisableEvent_64_95(EXTI_InitStruct->Line_64_95);
+ }
+
+#if defined(DUAL_CORE)
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_C2_IT) == LL_EXTI_MODE_C2_IT)
+ {
+ /* Enable IT on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_EnableIT_64_95 (EXTI_InitStruct->Line_64_95);
+ }
+ else
+ {
+ /* Disable IT on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_DisableIT_64_95 (EXTI_InitStruct->Line_64_95);
+ }
+
+ if((EXTI_InitStruct->Mode & LL_EXTI_MODE_C2_EVENT) == LL_EXTI_MODE_C2_EVENT)
+ {
+ /* Enable event on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_EnableEvent_64_95(EXTI_InitStruct->Line_64_95);
+ }
+ else
+ {
+ /* Disable event on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_DisableEvent_64_95(EXTI_InitStruct->Line_64_95);
+ }
+#endif /* DUAL_CORE */
+
+ if (EXTI_InitStruct->Trigger != LL_EXTI_TRIGGER_NONE)
+ {
+ switch (EXTI_InitStruct->Trigger)
+ {
+ case LL_EXTI_TRIGGER_RISING:
+ /* First Disable Falling Trigger on provided Lines */
+ LL_EXTI_DisableFallingTrig_64_95(EXTI_InitStruct->Line_64_95);
+ /* Then Enable IT on provided Lines */
+ LL_EXTI_EnableRisingTrig_64_95(EXTI_InitStruct->Line_64_95);
+ break;
+ case LL_EXTI_TRIGGER_FALLING:
+ /* First Disable Rising Trigger on provided Lines */
+ LL_EXTI_DisableRisingTrig_64_95(EXTI_InitStruct->Line_64_95);
+ /* Then Enable Falling Trigger on provided Lines */
+ LL_EXTI_EnableFallingTrig_64_95(EXTI_InitStruct->Line_64_95);
+ break;
+ case LL_EXTI_TRIGGER_RISING_FALLING:
+ LL_EXTI_EnableRisingTrig_64_95(EXTI_InitStruct->Line_64_95);
+ LL_EXTI_EnableFallingTrig_64_95(EXTI_InitStruct->Line_64_95);
+ break;
+ default:
+ status = ERROR;
+ break;
+ }
+ }
+ }
+ }
+ else /* DISABLE LineCommand */
+ {
+ /* Disable IT on provided Lines for Cortex-M7*/
+ LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
+ LL_EXTI_DisableIT_32_63(EXTI_InitStruct->Line_32_63);
+ LL_EXTI_DisableIT_64_95(EXTI_InitStruct->Line_64_95);
+
+ /* Disable event on provided Lines for Cortex-M7 */
+ LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
+ LL_EXTI_DisableEvent_32_63(EXTI_InitStruct->Line_32_63);
+ LL_EXTI_DisableEvent_64_95(EXTI_InitStruct->Line_64_95);
+
+#if defined(DUAL_CORE)
+ /* Disable IT on provided Lines for Cortex-M4*/
+ LL_C2_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
+ LL_C2_EXTI_DisableIT_32_63(EXTI_InitStruct->Line_32_63);
+ LL_C2_EXTI_DisableIT_64_95(EXTI_InitStruct->Line_64_95);
+
+ /* Disable event on provided Lines for Cortex-M4 */
+ LL_C2_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
+ LL_C2_EXTI_DisableEvent_32_63(EXTI_InitStruct->Line_32_63);
+ LL_C2_EXTI_DisableEvent_64_95(EXTI_InitStruct->Line_64_95);
+#endif /* DUAL_CORE */
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_EXTI_InitTypeDef field to default value.
+ * @param EXTI_InitStruct Pointer to a @ref LL_EXTI_InitTypeDef structure.
+ * @retval None
+ */
+void LL_EXTI_StructInit(LL_EXTI_InitTypeDef *EXTI_InitStruct)
+{
+ EXTI_InitStruct->Line_0_31 = LL_EXTI_LINE_NONE;
+ EXTI_InitStruct->Line_32_63 = LL_EXTI_LINE_NONE;
+ EXTI_InitStruct->Line_64_95 = LL_EXTI_LINE_NONE;
+ EXTI_InitStruct->LineCommand = DISABLE;
+ EXTI_InitStruct->Mode = LL_EXTI_MODE_IT;
+ EXTI_InitStruct->Trigger = LL_EXTI_TRIGGER_FALLING;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined (EXTI) */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_fmc.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_fmc.c
new file mode 100644
index 0000000000..7625f212bd
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/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
+ *
+ @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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#if (((defined HAL_NOR_MODULE_ENABLED || defined HAL_SRAM_MODULE_ENABLED)) || defined HAL_NAND_MODULE_ENABLED || defined HAL_SDRAM_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 */
+#if defined(FMC_BWTRx_BUSTURN)
+#define BWTR_CLEAR_MASK ((uint32_t)(FMC_BWTRx_ADDSET | FMC_BWTRx_ADDHLD |\
+ FMC_BWTRx_DATAST | FMC_BWTRx_BUSTURN |\
+ FMC_BWTRx_ACCMOD))
+#else
+#define BWTR_CLEAR_MASK ((uint32_t)(FMC_BWTRx_ADDSET | FMC_BWTRx_ADDHLD |\
+ FMC_BWTRx_DATAST | FMC_BWTRx_ACCMOD))
+#endif /* FMC_BWTRx_BUSTURN */
+
+/* --- 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, 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, 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 */
+ MODIFY_REG(Device->BTCR[Bank + 1U], BTR_CLEAR_MASK, (Timing->AddressSetupTime |
+ ((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] & ~(((uint32_t)0x0F) << 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, 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));
+#if defined(FMC_BWTRx_BUSTURN)
+ assert_param(IS_FMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration));
+#endif /* FMC_BWTRx_BUSTURN */
+ 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) |
+#if defined(FMC_BWTRx_BUSTURN)
+ Timing->AccessMode |
+ ((Timing->BusTurnAroundDuration) << FMC_BWTRx_BUSTURN_Pos)));
+#else
+ Timing->AccessMode));
+#endif /* FMC_BWTRx_BUSTURN */
+ }
+ 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, 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, 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 */
+ MODIFY_REG(Device->PMEM, PMEM_CLEAR_MASK, (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, 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 */
+ MODIFY_REG(Device->PATT, PATT_CLEAR_MASK, (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(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, 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, 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, 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 */
+ SET_BIT(Device->SDCMR, ((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(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 */
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_gpio.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_gpio.c
new file mode 100644
index 0000000000..176e27f8cd
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_gpio.c
@@ -0,0 +1,307 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_gpio.c
+ * @author MCD Application Team
+ * @brief GPIO LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_gpio.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI) || defined (GPIOJ) || defined (GPIOK)
+
+/** @addtogroup GPIO_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup GPIO_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_GPIO_PIN(__VALUE__) (((0x00000000U) < (__VALUE__)) && ((__VALUE__) <= (LL_GPIO_PIN_ALL)))
+
+#define IS_LL_GPIO_MODE(__VALUE__) (((__VALUE__) == LL_GPIO_MODE_INPUT) ||\
+ ((__VALUE__) == LL_GPIO_MODE_OUTPUT) ||\
+ ((__VALUE__) == LL_GPIO_MODE_ALTERNATE) ||\
+ ((__VALUE__) == LL_GPIO_MODE_ANALOG))
+
+#define IS_LL_GPIO_OUTPUT_TYPE(__VALUE__) (((__VALUE__) == LL_GPIO_OUTPUT_PUSHPULL) ||\
+ ((__VALUE__) == LL_GPIO_OUTPUT_OPENDRAIN))
+
+#define IS_LL_GPIO_SPEED(__VALUE__) (((__VALUE__) == LL_GPIO_SPEED_FREQ_LOW) ||\
+ ((__VALUE__) == LL_GPIO_SPEED_FREQ_MEDIUM) ||\
+ ((__VALUE__) == LL_GPIO_SPEED_FREQ_HIGH) ||\
+ ((__VALUE__) == LL_GPIO_SPEED_FREQ_VERY_HIGH))
+
+#define IS_LL_GPIO_PULL(__VALUE__) (((__VALUE__) == LL_GPIO_PULL_NO) ||\
+ ((__VALUE__) == LL_GPIO_PULL_UP) ||\
+ ((__VALUE__) == LL_GPIO_PULL_DOWN))
+
+#define IS_LL_GPIO_ALTERNATE(__VALUE__) (((__VALUE__) == LL_GPIO_AF_0 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_1 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_2 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_3 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_4 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_5 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_6 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_7 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_8 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_9 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_10 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_11 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_12 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_13 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_14 ) ||\
+ ((__VALUE__) == LL_GPIO_AF_15 ))
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup GPIO_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup GPIO_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize GPIO registers (Registers restored to their default values).
+ * @param GPIOx GPIO Port
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: GPIO registers are de-initialized
+ * - ERROR: Wrong GPIO Port
+ */
+ErrorStatus LL_GPIO_DeInit(GPIO_TypeDef *GPIOx)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
+
+ /* Force and Release reset on clock of GPIOx Port */
+ if (GPIOx == GPIOA)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOA);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOA);
+ }
+ else if (GPIOx == GPIOB)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOB);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOB);
+ }
+ else if (GPIOx == GPIOC)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOC);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOC);
+ }
+#if defined(GPIOD)
+ else if (GPIOx == GPIOD)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOD);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOD);
+ }
+#endif /* GPIOD */
+#if defined(GPIOE)
+ else if (GPIOx == GPIOE)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOE);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOE);
+ }
+#endif /* GPIOE */
+#if defined(GPIOF)
+ else if (GPIOx == GPIOF)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOF);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOF);
+ }
+#endif /* GPIOF */
+#if defined(GPIOG)
+ else if (GPIOx == GPIOG)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOG);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOG);
+ }
+#endif /* GPIOG */
+#if defined(GPIOH)
+ else if (GPIOx == GPIOH)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOH);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOH);
+ }
+#endif /* GPIOH */
+#if defined(GPIOI)
+ else if (GPIOx == GPIOI)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOI);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOI);
+ }
+#endif /* GPIOI */
+#if defined(GPIOJ)
+ else if (GPIOx == GPIOJ)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOJ);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOJ);
+ }
+#endif /* GPIOJ */
+#if defined(GPIOK)
+ else if (GPIOx == GPIOK)
+ {
+ LL_AHB4_GRP1_ForceReset(LL_AHB4_GRP1_PERIPH_GPIOK);
+ LL_AHB4_GRP1_ReleaseReset(LL_AHB4_GRP1_PERIPH_GPIOK);
+ }
+#endif /* GPIOK */
+ else
+ {
+ status = ERROR;
+ }
+
+ return (status);
+}
+
+/**
+ * @brief Initialize GPIO registers according to the specified parameters in GPIO_InitStruct.
+ * @param GPIOx GPIO Port
+ * @param GPIO_InitStruct pointer to a @ref LL_GPIO_InitTypeDef structure
+ * that contains the configuration information for the specified GPIO peripheral.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: GPIO registers are initialized according to GPIO_InitStruct content
+ * - ERROR: Not applicable
+ */
+ErrorStatus LL_GPIO_Init(GPIO_TypeDef *GPIOx, LL_GPIO_InitTypeDef *GPIO_InitStruct)
+{
+ uint32_t pinpos, currentpin;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
+ assert_param(IS_LL_GPIO_PIN(GPIO_InitStruct->Pin));
+ assert_param(IS_LL_GPIO_MODE(GPIO_InitStruct->Mode));
+ assert_param(IS_LL_GPIO_PULL(GPIO_InitStruct->Pull));
+
+ /* ------------------------- Configure the port pins ---------------- */
+ /* Initialize pinpos on first pin set */
+ pinpos = POSITION_VAL(GPIO_InitStruct->Pin);
+
+ /* Configure the port pins */
+ while (((GPIO_InitStruct->Pin) >> pinpos) != 0x00000000U)
+ {
+ /* Get current io position */
+ currentpin = (GPIO_InitStruct->Pin) & (0x00000001UL << pinpos);
+
+ if (currentpin != 0x00000000U)
+ {
+
+ if ((GPIO_InitStruct->Mode == LL_GPIO_MODE_OUTPUT) || (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE))
+ {
+ /* Check Speed mode parameters */
+ assert_param(IS_LL_GPIO_SPEED(GPIO_InitStruct->Speed));
+
+ /* Speed mode configuration */
+ LL_GPIO_SetPinSpeed(GPIOx, currentpin, GPIO_InitStruct->Speed);
+
+ /* Check Output mode parameters */
+ assert_param(IS_LL_GPIO_OUTPUT_TYPE(GPIO_InitStruct->OutputType));
+
+ /* Output mode configuration*/
+ LL_GPIO_SetPinOutputType(GPIOx, GPIO_InitStruct->Pin, GPIO_InitStruct->OutputType);
+
+ }
+
+ /* Pull-up Pull down resistor configuration*/
+ LL_GPIO_SetPinPull(GPIOx, currentpin, GPIO_InitStruct->Pull);
+
+ if (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE)
+ {
+ /* Check Alternate parameter */
+ assert_param(IS_LL_GPIO_ALTERNATE(GPIO_InitStruct->Alternate));
+
+ /* Alternate function configuration */
+ if (currentpin < LL_GPIO_PIN_8)
+ {
+ LL_GPIO_SetAFPin_0_7(GPIOx, currentpin, GPIO_InitStruct->Alternate);
+ }
+ else
+ {
+ LL_GPIO_SetAFPin_8_15(GPIOx, currentpin, GPIO_InitStruct->Alternate);
+ }
+ }
+
+ /* Pin Mode configuration */
+ LL_GPIO_SetPinMode(GPIOx, currentpin, GPIO_InitStruct->Mode);
+ }
+ pinpos++;
+ }
+
+ return (SUCCESS);
+}
+
+/**
+ * @brief Set each @ref LL_GPIO_InitTypeDef field to default value.
+ * @param GPIO_InitStruct pointer to a @ref LL_GPIO_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+
+void LL_GPIO_StructInit(LL_GPIO_InitTypeDef *GPIO_InitStruct)
+{
+ /* Reset GPIO init structure parameters values */
+ GPIO_InitStruct->Pin = LL_GPIO_PIN_ALL;
+ GPIO_InitStruct->Mode = LL_GPIO_MODE_ANALOG;
+ GPIO_InitStruct->Speed = LL_GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStruct->OutputType = LL_GPIO_OUTPUT_PUSHPULL;
+ GPIO_InitStruct->Pull = LL_GPIO_PULL_NO;
+ GPIO_InitStruct->Alternate = LL_GPIO_AF_0;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI) || defined (GPIOJ) || defined (GPIOK) */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_hrtim.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_hrtim.c
new file mode 100644
index 0000000000..a4879f7b66
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_hrtim.c
@@ -0,0 +1,83 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_hrtim.c
+ * @author MCD Application Team
+ * @brief HRTIM LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_hrtim.h"
+#include "stm32h7xx_ll_bus.h"
+
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (HRTIM1)
+
+/** @addtogroup HRTIM_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup HRTIM_LL_Exported_Functions
+ * @{
+ */
+/**
+ * @brief Set HRTIM instance registers to their reset values.
+ * @param HRTIMx High Resolution Timer instance
+ * @retval ErrorStatus enumeration value:
+ * - SUCCESS: HRTIMx registers are de-initialized
+ * - ERROR: invalid HRTIMx instance
+ */
+ErrorStatus LL_HRTIM_DeInit(HRTIM_TypeDef *HRTIMx)
+{
+ ErrorStatus result = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_HRTIM_ALL_INSTANCE(HRTIMx));
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_HRTIM);
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_HRTIM);
+ return result;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HRTIM1 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_i2c.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_i2c.c
new file mode 100644
index 0000000000..d10c71efeb
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_i2c.c
@@ -0,0 +1,243 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_i2c.c
+ * @author MCD Application Team
+ * @brief I2C LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_i2c.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (I2C1) || defined (I2C2) || defined (I2C3) || defined (I2C4)
+
+/** @defgroup I2C_LL I2C
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup I2C_LL_Private_Macros
+ * @{
+ */
+
+#define IS_LL_I2C_PERIPHERAL_MODE(__VALUE__) (((__VALUE__) == LL_I2C_MODE_I2C) || \
+ ((__VALUE__) == LL_I2C_MODE_SMBUS_HOST) || \
+ ((__VALUE__) == LL_I2C_MODE_SMBUS_DEVICE) || \
+ ((__VALUE__) == LL_I2C_MODE_SMBUS_DEVICE_ARP))
+
+#define IS_LL_I2C_ANALOG_FILTER(__VALUE__) (((__VALUE__) == LL_I2C_ANALOGFILTER_ENABLE) || \
+ ((__VALUE__) == LL_I2C_ANALOGFILTER_DISABLE))
+
+#define IS_LL_I2C_DIGITAL_FILTER(__VALUE__) ((__VALUE__) <= 0x0000000FU)
+
+#define IS_LL_I2C_OWN_ADDRESS1(__VALUE__) ((__VALUE__) <= 0x000003FFU)
+
+#define IS_LL_I2C_TYPE_ACKNOWLEDGE(__VALUE__) (((__VALUE__) == LL_I2C_ACK) || \
+ ((__VALUE__) == LL_I2C_NACK))
+
+#define IS_LL_I2C_OWN_ADDRSIZE(__VALUE__) (((__VALUE__) == LL_I2C_OWNADDRESS1_7BIT) || \
+ ((__VALUE__) == LL_I2C_OWNADDRESS1_10BIT))
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup I2C_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup I2C_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize the I2C registers to their default reset values.
+ * @param I2Cx I2C Instance.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: I2C registers are de-initialized
+ * - ERROR: I2C registers are not de-initialized
+ */
+ErrorStatus LL_I2C_DeInit(I2C_TypeDef *I2Cx)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the I2C Instance I2Cx */
+ assert_param(IS_I2C_ALL_INSTANCE(I2Cx));
+
+ if (I2Cx == I2C1)
+ {
+ /* Force reset of I2C clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
+
+ /* Release reset of I2C clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
+ }
+ else if (I2Cx == I2C2)
+ {
+ /* Force reset of I2C clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C2);
+
+ /* Release reset of I2C clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C2);
+
+ }
+ else if (I2Cx == I2C3)
+ {
+ /* Force reset of I2C clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
+
+ /* Release reset of I2C clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
+ }
+ else if (I2Cx == I2C4)
+ {
+ /* Force reset of I2C clock */
+ LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_I2C4);
+
+ /* Release reset of I2C clock */
+ LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_I2C4);
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Initialize the I2C registers according to the specified parameters in I2C_InitStruct.
+ * @param I2Cx I2C Instance.
+ * @param I2C_InitStruct pointer to a @ref LL_I2C_InitTypeDef structure.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: I2C registers are initialized
+ * - ERROR: Not applicable
+ */
+ErrorStatus LL_I2C_Init(I2C_TypeDef *I2Cx, LL_I2C_InitTypeDef *I2C_InitStruct)
+{
+ /* Check the I2C Instance I2Cx */
+ assert_param(IS_I2C_ALL_INSTANCE(I2Cx));
+
+ /* Check the I2C parameters from I2C_InitStruct */
+ assert_param(IS_LL_I2C_PERIPHERAL_MODE(I2C_InitStruct->PeripheralMode));
+ assert_param(IS_LL_I2C_ANALOG_FILTER(I2C_InitStruct->AnalogFilter));
+ assert_param(IS_LL_I2C_DIGITAL_FILTER(I2C_InitStruct->DigitalFilter));
+ assert_param(IS_LL_I2C_OWN_ADDRESS1(I2C_InitStruct->OwnAddress1));
+ assert_param(IS_LL_I2C_TYPE_ACKNOWLEDGE(I2C_InitStruct->TypeAcknowledge));
+ assert_param(IS_LL_I2C_OWN_ADDRSIZE(I2C_InitStruct->OwnAddrSize));
+
+ /* Disable the selected I2Cx Peripheral */
+ LL_I2C_Disable(I2Cx);
+
+ /*---------------------------- I2Cx CR1 Configuration ------------------------
+ * Configure the analog and digital noise filters with parameters :
+ * - AnalogFilter: I2C_CR1_ANFOFF bit
+ * - DigitalFilter: I2C_CR1_DNF[3:0] bits
+ */
+ LL_I2C_ConfigFilters(I2Cx, I2C_InitStruct->AnalogFilter, I2C_InitStruct->DigitalFilter);
+
+ /*---------------------------- I2Cx TIMINGR Configuration --------------------
+ * Configure the SDA setup, hold time and the SCL high, low period with parameter :
+ * - Timing: I2C_TIMINGR_PRESC[3:0], I2C_TIMINGR_SCLDEL[3:0], I2C_TIMINGR_SDADEL[3:0],
+ * I2C_TIMINGR_SCLH[7:0] and I2C_TIMINGR_SCLL[7:0] bits
+ */
+ LL_I2C_SetTiming(I2Cx, I2C_InitStruct->Timing);
+
+ /* Enable the selected I2Cx Peripheral */
+ LL_I2C_Enable(I2Cx);
+
+ /*---------------------------- I2Cx OAR1 Configuration -----------------------
+ * Disable, Configure and Enable I2Cx device own address 1 with parameters :
+ * - OwnAddress1: I2C_OAR1_OA1[9:0] bits
+ * - OwnAddrSize: I2C_OAR1_OA1MODE bit
+ */
+ LL_I2C_DisableOwnAddress1(I2Cx);
+ LL_I2C_SetOwnAddress1(I2Cx, I2C_InitStruct->OwnAddress1, I2C_InitStruct->OwnAddrSize);
+
+ /* OwnAdress1 == 0 is reserved for General Call address */
+ if (I2C_InitStruct->OwnAddress1 != 0U)
+ {
+ LL_I2C_EnableOwnAddress1(I2Cx);
+ }
+
+ /*---------------------------- I2Cx MODE Configuration -----------------------
+ * Configure I2Cx peripheral mode with parameter :
+ * - PeripheralMode: I2C_CR1_SMBDEN and I2C_CR1_SMBHEN bits
+ */
+ LL_I2C_SetMode(I2Cx, I2C_InitStruct->PeripheralMode);
+
+ /*---------------------------- I2Cx CR2 Configuration ------------------------
+ * Configure the ACKnowledge or Non ACKnowledge condition
+ * after the address receive match code or next received byte with parameter :
+ * - TypeAcknowledge: I2C_CR2_NACK bit
+ */
+ LL_I2C_AcknowledgeNextData(I2Cx, I2C_InitStruct->TypeAcknowledge);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Set each @ref LL_I2C_InitTypeDef field to default value.
+ * @param I2C_InitStruct Pointer to a @ref LL_I2C_InitTypeDef structure.
+ * @retval None
+ */
+void LL_I2C_StructInit(LL_I2C_InitTypeDef *I2C_InitStruct)
+{
+ /* Set I2C_InitStruct fields to default values */
+ I2C_InitStruct->PeripheralMode = LL_I2C_MODE_I2C;
+ I2C_InitStruct->Timing = 0U;
+ I2C_InitStruct->AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
+ I2C_InitStruct->DigitalFilter = 0U;
+ I2C_InitStruct->OwnAddress1 = 0U;
+ I2C_InitStruct->TypeAcknowledge = LL_I2C_NACK;
+ I2C_InitStruct->OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* I2C1 || I2C2 || I2C3 || I2C4 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_lptim.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_lptim.c
new file mode 100644
index 0000000000..154d8828c7
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_lptim.c
@@ -0,0 +1,355 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_lptim.c
+ * @author MCD Application Team
+ * @brief LPTIM LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_lptim.h"
+#include "stm32h7xx_ll_bus.h"
+#include "stm32h7xx_ll_rcc.h"
+
+
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (LPTIM1) || defined (LPTIM2) || defined (LPTIM3) || defined (LPTIM4) || defined (LPTIM5)
+
+/** @addtogroup LPTIM_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup LPTIM_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_LPTIM_CLOCK_SOURCE(__VALUE__) (((__VALUE__) == LL_LPTIM_CLK_SOURCE_INTERNAL) \
+ || ((__VALUE__) == LL_LPTIM_CLK_SOURCE_EXTERNAL))
+
+#define IS_LL_LPTIM_CLOCK_PRESCALER(__VALUE__) (((__VALUE__) == LL_LPTIM_PRESCALER_DIV1) \
+ || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV2) \
+ || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV4) \
+ || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV8) \
+ || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV16) \
+ || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV32) \
+ || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV64) \
+ || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV128))
+
+#define IS_LL_LPTIM_WAVEFORM(__VALUE__) (((__VALUE__) == LL_LPTIM_OUTPUT_WAVEFORM_PWM) \
+ || ((__VALUE__) == LL_LPTIM_OUTPUT_WAVEFORM_SETONCE))
+
+#define IS_LL_LPTIM_OUTPUT_POLARITY(__VALUE__) (((__VALUE__) == LL_LPTIM_OUTPUT_POLARITY_REGULAR) \
+ || ((__VALUE__) == LL_LPTIM_OUTPUT_POLARITY_INVERSE))
+/**
+ * @}
+ */
+
+
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup LPTIM_Private_Functions LPTIM Private Functions
+ * @{
+ */
+/**
+ * @}
+ */
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup LPTIM_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup LPTIM_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief Set LPTIMx registers to their reset values.
+ * @param LPTIMx LP Timer instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: LPTIMx registers are de-initialized
+ * - ERROR: invalid LPTIMx instance
+ */
+ErrorStatus LL_LPTIM_DeInit(LPTIM_TypeDef *LPTIMx)
+{
+ ErrorStatus result = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(LPTIMx));
+
+ if (LPTIMx == LPTIM1)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_LPTIM1);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_LPTIM1);
+ }
+ else if (LPTIMx == LPTIM2)
+ {
+ LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM2);
+ LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM2);
+ }
+#if defined(LPTIM3)
+ else if (LPTIMx == LPTIM3)
+ {
+ LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM3);
+ LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM3);
+ }
+#endif /* LPTIM3 */
+#if defined(LPTIM4)
+ else if (LPTIMx == LPTIM4)
+ {
+ LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM4);
+ LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM4);
+ }
+#endif /* LPTIM4 */
+#if defined(LPTIM5)
+ else if (LPTIMx == LPTIM5)
+ {
+ LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM5);
+ LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM5);
+ }
+#endif /* LPTIM5 */
+ else
+ {
+ result = ERROR;
+ }
+
+ return result;
+}
+
+/**
+ * @brief Set each fields of the LPTIM_InitStruct structure to its default
+ * value.
+ * @param LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure
+ * @retval None
+ */
+void LL_LPTIM_StructInit(LL_LPTIM_InitTypeDef *LPTIM_InitStruct)
+{
+ /* Set the default configuration */
+ LPTIM_InitStruct->ClockSource = LL_LPTIM_CLK_SOURCE_INTERNAL;
+ LPTIM_InitStruct->Prescaler = LL_LPTIM_PRESCALER_DIV1;
+ LPTIM_InitStruct->Waveform = LL_LPTIM_OUTPUT_WAVEFORM_PWM;
+ LPTIM_InitStruct->Polarity = LL_LPTIM_OUTPUT_POLARITY_REGULAR;
+}
+
+/**
+ * @brief Configure the LPTIMx peripheral according to the specified parameters.
+ * @note LL_LPTIM_Init can only be called when the LPTIM instance is disabled.
+ * @note LPTIMx can be disabled using unitary function @ref LL_LPTIM_Disable().
+ * @param LPTIMx LP Timer Instance
+ * @param LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: LPTIMx instance has been initialized
+ * - ERROR: LPTIMx instance hasn't been initialized
+ */
+ErrorStatus LL_LPTIM_Init(LPTIM_TypeDef *LPTIMx, LL_LPTIM_InitTypeDef *LPTIM_InitStruct)
+{
+ ErrorStatus result = SUCCESS;
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(LPTIMx));
+ assert_param(IS_LL_LPTIM_CLOCK_SOURCE(LPTIM_InitStruct->ClockSource));
+ assert_param(IS_LL_LPTIM_CLOCK_PRESCALER(LPTIM_InitStruct->Prescaler));
+ assert_param(IS_LL_LPTIM_WAVEFORM(LPTIM_InitStruct->Waveform));
+ assert_param(IS_LL_LPTIM_OUTPUT_POLARITY(LPTIM_InitStruct->Polarity));
+
+ /* The LPTIMx_CFGR register must only be modified when the LPTIM is disabled
+ (ENABLE bit is reset to 0).
+ */
+ if (LL_LPTIM_IsEnabled(LPTIMx) == 1UL)
+ {
+ result = ERROR;
+ }
+ else
+ {
+ /* Set CKSEL bitfield according to ClockSource value */
+ /* Set PRESC bitfield according to Prescaler value */
+ /* Set WAVE bitfield according to Waveform value */
+ /* Set WAVEPOL bitfield according to Polarity value */
+ MODIFY_REG(LPTIMx->CFGR,
+ (LPTIM_CFGR_CKSEL | LPTIM_CFGR_PRESC | LPTIM_CFGR_WAVE | LPTIM_CFGR_WAVPOL),
+ LPTIM_InitStruct->ClockSource | \
+ LPTIM_InitStruct->Prescaler | \
+ LPTIM_InitStruct->Waveform | \
+ LPTIM_InitStruct->Polarity);
+ }
+
+ return result;
+}
+
+/**
+ * @brief Disable the LPTIM instance
+ * @rmtoll CR ENABLE LL_LPTIM_Disable
+ * @param LPTIMx Low-Power Timer instance
+ * @note The following sequence is required to solve LPTIM disable HW limitation.
+ * Please check Errata Sheet ES0335 for more details under "MCU may remain
+ * stuck in LPTIM interrupt when entering Stop mode" section.
+ * @retval None
+ */
+void LL_LPTIM_Disable(LPTIM_TypeDef *LPTIMx)
+{
+ LL_RCC_ClocksTypeDef rcc_clock;
+ uint32_t tmpclksource = 0;
+ uint32_t tmpIER;
+ uint32_t tmpCFGR;
+ uint32_t tmpCMP;
+ uint32_t tmpARR;
+ uint32_t tmpCFGR2;
+
+ /* Check the parameters */
+ assert_param(IS_LPTIM_INSTANCE(LPTIMx));
+
+ __disable_irq();
+
+ /********** Save LPTIM Config *********/
+ /* Save LPTIM source clock */
+ switch ((uint32_t)LPTIMx)
+ {
+ case LPTIM1_BASE:
+ tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE);
+ break;
+ case LPTIM2_BASE:
+ tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE);
+ break;
+#if defined(LPTIM3)&&defined(LPTIM4)&&defined(LPTIM5)
+ case LPTIM3_BASE:
+ case LPTIM4_BASE:
+ case LPTIM5_BASE:
+ tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM345_CLKSOURCE);
+ break;
+#elif defined(LPTIM3)
+ case LPTIM3_BASE:
+ tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM3_CLKSOURCE);
+ break;
+#endif /* LPTIM3 && LPTIM4 && LPTIM5 */
+ default:
+ break;
+ }
+
+ /* Save LPTIM configuration registers */
+ tmpIER = LPTIMx->IER;
+ tmpCFGR = LPTIMx->CFGR;
+ tmpCMP = LPTIMx->CMP;
+ tmpARR = LPTIMx->ARR;
+ tmpCFGR2 = LPTIMx->CFGR2;
+
+ /************* Reset LPTIM ************/
+ (void)LL_LPTIM_DeInit(LPTIMx);
+
+ /********* Restore LPTIM Config *******/
+ LL_RCC_GetSystemClocksFreq(&rcc_clock);
+
+ if ((tmpCMP != 0UL) || (tmpARR != 0UL))
+ {
+ /* Force LPTIM source kernel clock from APB */
+ switch ((uint32_t)LPTIMx)
+ {
+ case LPTIM1_BASE:
+ LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_PCLK1);
+ break;
+ case LPTIM2_BASE:
+ LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_PCLK4);
+ break;
+#if defined(LPTIM3)&&defined(LPTIM4)&&defined(LPTIM5)
+ case LPTIM3_BASE:
+ case LPTIM4_BASE:
+ case LPTIM5_BASE:
+ LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM345_CLKSOURCE_PCLK4);
+ break;
+#elif defined(LPTIM3)
+ case LPTIM3_BASE:
+ LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM3_CLKSOURCE_PCLK4);
+ break;
+#endif /* LPTIM3 && LPTIM4 && LPTIM5*/
+ default:
+ break;
+ }
+
+ if (tmpCMP != 0UL)
+ {
+ /* Restore CMP and ARR registers (LPTIM should be enabled first) */
+ LPTIMx->CR |= LPTIM_CR_ENABLE;
+ LPTIMx->CMP = tmpCMP;
+
+ /* Polling on CMP write ok status after above restore operation */
+ do
+ {
+ rcc_clock.SYSCLK_Frequency--; /* Used for timeout */
+ }
+ while (((LL_LPTIM_IsActiveFlag_CMPOK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL));
+
+ LL_LPTIM_ClearFlag_CMPOK(LPTIMx);
+ }
+
+ if (tmpARR != 0UL)
+ {
+ LPTIMx->CR |= LPTIM_CR_ENABLE;
+ LPTIMx->ARR = tmpARR;
+
+ LL_RCC_GetSystemClocksFreq(&rcc_clock);
+ /* Polling on ARR write ok status after above restore operation */
+ do
+ {
+ rcc_clock.SYSCLK_Frequency--; /* Used for timeout */
+ }
+ while (((LL_LPTIM_IsActiveFlag_ARROK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL));
+
+ LL_LPTIM_ClearFlag_ARROK(LPTIMx);
+ }
+
+
+ /* Restore LPTIM source kernel clock */
+ LL_RCC_SetLPTIMClockSource(tmpclksource);
+ }
+
+ /* Restore configuration registers (LPTIM should be disabled first) */
+ LPTIMx->CR &= ~(LPTIM_CR_ENABLE);
+ LPTIMx->IER = tmpIER;
+ LPTIMx->CFGR = tmpCFGR;
+ LPTIMx->CFGR2 = tmpCFGR2;
+
+ __enable_irq();
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* LPTIM1 || LPTIM2 || LPTIM3 || LPTIM4 || LPTIM5 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_lpuart.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_lpuart.c
new file mode 100644
index 0000000000..6eba1d0288
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_lpuart.c
@@ -0,0 +1,283 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_lpuart.c
+ * @author MCD Application Team
+ * @brief LPUART LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_lpuart.h"
+#include "stm32h7xx_ll_rcc.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (LPUART1)
+
+/** @addtogroup LPUART_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup LPUART_LL_Private_Constants
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup LPUART_LL_Private_Macros
+ * @{
+ */
+
+/* Check of parameters for configuration of LPUART registers */
+
+#define IS_LL_LPUART_PRESCALER(__VALUE__) (((__VALUE__) == LL_LPUART_PRESCALER_DIV1) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV2) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV4) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV6) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV8) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV10) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV12) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV16) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV32) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV64) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV128) \
+ || ((__VALUE__) == LL_LPUART_PRESCALER_DIV256))
+
+/* __BAUDRATE__ Depending on constraints applicable for LPUART BRR register */
+/* value : */
+/* - fck must be in the range [3 x baudrate, 4096 x baudrate] */
+/* - LPUART_BRR register value should be >= 0x300 */
+/* - LPUART_BRR register value should be <= 0xFFFFF (20 bits) */
+/* Baudrate specified by the user should belong to [8, 33000000].*/
+#define IS_LL_LPUART_BAUDRATE(__BAUDRATE__) (((__BAUDRATE__) <= 33000000U) && ((__BAUDRATE__) >= 8U))
+
+/* __VALUE__ BRR content must be greater than or equal to 0x300. */
+#define IS_LL_LPUART_BRR_MIN(__VALUE__) ((__VALUE__) >= 0x300U)
+
+/* __VALUE__ BRR content must be lower than or equal to 0xFFFFF. */
+#define IS_LL_LPUART_BRR_MAX(__VALUE__) ((__VALUE__) <= 0x000FFFFFU)
+
+#define IS_LL_LPUART_DIRECTION(__VALUE__) (((__VALUE__) == LL_LPUART_DIRECTION_NONE) \
+ || ((__VALUE__) == LL_LPUART_DIRECTION_RX) \
+ || ((__VALUE__) == LL_LPUART_DIRECTION_TX) \
+ || ((__VALUE__) == LL_LPUART_DIRECTION_TX_RX))
+
+#define IS_LL_LPUART_PARITY(__VALUE__) (((__VALUE__) == LL_LPUART_PARITY_NONE) \
+ || ((__VALUE__) == LL_LPUART_PARITY_EVEN) \
+ || ((__VALUE__) == LL_LPUART_PARITY_ODD))
+
+#define IS_LL_LPUART_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_LPUART_DATAWIDTH_7B) \
+ || ((__VALUE__) == LL_LPUART_DATAWIDTH_8B) \
+ || ((__VALUE__) == LL_LPUART_DATAWIDTH_9B))
+
+#define IS_LL_LPUART_STOPBITS(__VALUE__) (((__VALUE__) == LL_LPUART_STOPBITS_1) \
+ || ((__VALUE__) == LL_LPUART_STOPBITS_2))
+
+#define IS_LL_LPUART_HWCONTROL(__VALUE__) (((__VALUE__) == LL_LPUART_HWCONTROL_NONE) \
+ || ((__VALUE__) == LL_LPUART_HWCONTROL_RTS) \
+ || ((__VALUE__) == LL_LPUART_HWCONTROL_CTS) \
+ || ((__VALUE__) == LL_LPUART_HWCONTROL_RTS_CTS))
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup LPUART_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup LPUART_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize LPUART registers (Registers restored to their default values).
+ * @param LPUARTx LPUART Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: LPUART registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_LPUART_DeInit(USART_TypeDef *LPUARTx)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_LPUART_INSTANCE(LPUARTx));
+
+ if (LPUARTx == LPUART1)
+ {
+ /* Force reset of LPUART peripheral */
+ LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPUART1);
+
+ /* Release reset of LPUART peripheral */
+ LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPUART1);
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ return (status);
+}
+
+/**
+ * @brief Initialize LPUART registers according to the specified
+ * parameters in LPUART_InitStruct.
+ * @note As some bits in LPUART configuration registers can only be written when the LPUART is disabled (USART_CR1_UE bit =0),
+ * LPUART Peripheral should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
+ * @note Baud rate value stored in LPUART_InitStruct BaudRate field, should be valid (different from 0).
+ * @param LPUARTx LPUART Instance
+ * @param LPUART_InitStruct pointer to a @ref LL_LPUART_InitTypeDef structure
+ * that contains the configuration information for the specified LPUART peripheral.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: LPUART registers are initialized according to LPUART_InitStruct content
+ * - ERROR: Problem occurred during LPUART Registers initialization
+ */
+ErrorStatus LL_LPUART_Init(USART_TypeDef *LPUARTx, LL_LPUART_InitTypeDef *LPUART_InitStruct)
+{
+ ErrorStatus status = ERROR;
+ uint32_t periphclk;
+
+ /* Check the parameters */
+ assert_param(IS_LPUART_INSTANCE(LPUARTx));
+ assert_param(IS_LL_LPUART_PRESCALER(LPUART_InitStruct->PrescalerValue));
+ assert_param(IS_LL_LPUART_BAUDRATE(LPUART_InitStruct->BaudRate));
+ assert_param(IS_LL_LPUART_DATAWIDTH(LPUART_InitStruct->DataWidth));
+ assert_param(IS_LL_LPUART_STOPBITS(LPUART_InitStruct->StopBits));
+ assert_param(IS_LL_LPUART_PARITY(LPUART_InitStruct->Parity));
+ assert_param(IS_LL_LPUART_DIRECTION(LPUART_InitStruct->TransferDirection));
+ assert_param(IS_LL_LPUART_HWCONTROL(LPUART_InitStruct->HardwareFlowControl));
+
+ /* LPUART needs to be in disabled state, in order to be able to configure some bits in
+ CRx registers. Otherwise (LPUART not in Disabled state) => return ERROR */
+ if (LL_LPUART_IsEnabled(LPUARTx) == 0U)
+ {
+ /*---------------------------- LPUART CR1 Configuration -----------------------
+ * Configure LPUARTx CR1 (LPUART Word Length, Parity and Transfer Direction bits) with parameters:
+ * - DataWidth: USART_CR1_M bits according to LPUART_InitStruct->DataWidth value
+ * - Parity: USART_CR1_PCE, USART_CR1_PS bits according to LPUART_InitStruct->Parity value
+ * - TransferDirection: USART_CR1_TE, USART_CR1_RE bits according to LPUART_InitStruct->TransferDirection value
+ */
+ MODIFY_REG(LPUARTx->CR1,
+ (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE),
+ (LPUART_InitStruct->DataWidth | LPUART_InitStruct->Parity | LPUART_InitStruct->TransferDirection));
+
+ /*---------------------------- LPUART CR2 Configuration -----------------------
+ * Configure LPUARTx CR2 (Stop bits) with parameters:
+ * - Stop Bits: USART_CR2_STOP bits according to LPUART_InitStruct->StopBits value.
+ */
+ LL_LPUART_SetStopBitsLength(LPUARTx, LPUART_InitStruct->StopBits);
+
+ /*---------------------------- LPUART CR3 Configuration -----------------------
+ * Configure LPUARTx CR3 (Hardware Flow Control) with parameters:
+ * - HardwareFlowControl: USART_CR3_RTSE, USART_CR3_CTSE bits according to LPUART_InitStruct->HardwareFlowControl value.
+ */
+ LL_LPUART_SetHWFlowCtrl(LPUARTx, LPUART_InitStruct->HardwareFlowControl);
+
+ /*---------------------------- LPUART BRR Configuration -----------------------
+ * Retrieve Clock frequency used for LPUART Peripheral
+ */
+ periphclk = LL_RCC_GetLPUARTClockFreq(LL_RCC_LPUART1_CLKSOURCE);
+
+ /* Configure the LPUART Baud Rate :
+ - prescaler value is required
+ - valid baud rate value (different from 0) is required
+ - Peripheral clock as returned by RCC service, should be valid (different from 0).
+ */
+ if ((periphclk != LL_RCC_PERIPH_FREQUENCY_NO)
+ && (LPUART_InitStruct->BaudRate != 0U))
+ {
+ status = SUCCESS;
+ LL_LPUART_SetBaudRate(LPUARTx,
+ periphclk,
+ LPUART_InitStruct->PrescalerValue,
+ LPUART_InitStruct->BaudRate);
+
+ /* Check BRR is greater than or equal to 0x300 */
+ assert_param(IS_LL_LPUART_BRR_MIN(LPUARTx->BRR));
+
+ /* Check BRR is lower than or equal to 0xFFFFF */
+ assert_param(IS_LL_LPUART_BRR_MAX(LPUARTx->BRR));
+ }
+
+ /*---------------------------- LPUART PRESC Configuration -----------------------
+ * Configure LPUARTx PRESC (Prescaler) with parameters:
+ * - PrescalerValue: LPUART_PRESC_PRESCALER bits according to LPUART_InitStruct->PrescalerValue value.
+ */
+ LL_LPUART_SetPrescaler(LPUARTx, LPUART_InitStruct->PrescalerValue);
+ }
+
+ return (status);
+}
+
+/**
+ * @brief Set each @ref LL_LPUART_InitTypeDef field to default value.
+ * @param LPUART_InitStruct pointer to a @ref LL_LPUART_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+
+void LL_LPUART_StructInit(LL_LPUART_InitTypeDef *LPUART_InitStruct)
+{
+ /* Set LPUART_InitStruct fields to default values */
+ LPUART_InitStruct->PrescalerValue = LL_LPUART_PRESCALER_DIV1;
+ LPUART_InitStruct->BaudRate = 9600U;
+ LPUART_InitStruct->DataWidth = LL_LPUART_DATAWIDTH_8B;
+ LPUART_InitStruct->StopBits = LL_LPUART_STOPBITS_1;
+ LPUART_InitStruct->Parity = LL_LPUART_PARITY_NONE ;
+ LPUART_InitStruct->TransferDirection = LL_LPUART_DIRECTION_TX_RX;
+ LPUART_InitStruct->HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined (LPUART1) */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_mdma.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_mdma.c
new file mode 100644
index 0000000000..a0a01cf364
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_mdma.c
@@ -0,0 +1,782 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_mdma.c
+ * @author MCD Application Team
+ * @brief MDMA LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_mdma.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (MDMA)
+
+/** @defgroup MDMA_LL MDMA
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup MDMA_LL_Private_Macros
+ * @{
+ */
+
+#define IS_LL_MDMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) (((INSTANCE) == MDMA) && \
+ (((CHANNEL) == LL_MDMA_CHANNEL_0) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_1) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_2) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_3) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_4) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_5) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_6) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_7) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_8) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_9) || \
+ ((CHANNEL) == LL_MDMA_CHANNEL_10)|| \
+ ((CHANNEL) == LL_MDMA_CHANNEL_11)|| \
+ ((CHANNEL) == LL_MDMA_CHANNEL_12)|| \
+ ((CHANNEL) == LL_MDMA_CHANNEL_13)|| \
+ ((CHANNEL) == LL_MDMA_CHANNEL_14)|| \
+ ((CHANNEL) == LL_MDMA_CHANNEL_15)|| \
+ ((CHANNEL) == LL_MDMA_CHANNEL_ALL)))
+
+#define IS_LL_MDMA_BLK_DATALENGTH(__VALUE__) ((__VALUE__) <= 0x00010000U)
+
+#define IS_LL_MDMA_BLK_REPEATCOUNT(__VALUE__) ((__VALUE__) <= 0x00000FFFU)
+
+#define IS_LL_MDMA_WORDENDIANESS(__VALUE__) (((__VALUE__) == LL_MDMA_WORD_ENDIANNESS_PRESERVE) || \
+ ((__VALUE__) == LL_MDMA_WORD_ENDIANNESS_EXCHANGE))
+
+#define IS_LL_MDMA_HALFWORDENDIANESS(__VALUE__) (((__VALUE__) == LL_MDMA_HALFWORD_ENDIANNESS_PRESERVE) || \
+ ((__VALUE__) == LL_MDMA_HALFWORD_ENDIANNESS_EXCHANGE))
+
+#define IS_LL_MDMA_BYTEENDIANESS(__VALUE__) (((__VALUE__) == LL_MDMA_BYTE_ENDIANNESS_PRESERVE) || \
+ ((__VALUE__) == LL_MDMA_BYTE_ENDIANNESS_EXCHANGE))
+
+#define IS_LL_MDMA_PRIORITY(__VALUE__) (((__VALUE__) == LL_MDMA_PRIORITY_LOW) || \
+ ((__VALUE__) == LL_MDMA_PRIORITY_MEDIUM) || \
+ ((__VALUE__) == LL_MDMA_PRIORITY_HIGH) || \
+ ((__VALUE__) == LL_MDMA_PRIORITY_VERYHIGH))
+
+#define IS_LL_MDMA_BUFFWRITEMODE(__VALUE__) (((__VALUE__) == LL_MDMA_BUFF_WRITE_DISABLE) || \
+ ((__VALUE__) == LL_MDMA_BUFF_WRITE_ENABLE))
+
+#define IS_LL_MDMA_REQUESTMODE(__VALUE__) (((__VALUE__) == LL_MDMA_REQUEST_MODE_HW) || \
+ ((__VALUE__) == LL_MDMA_REQUEST_MODE_SW))
+
+#define IS_LL_MDMA_TRIGGERMODE(__VALUE__) (((__VALUE__) == LL_MDMA_BUFFER_TRANSFER) || \
+ ((__VALUE__) == LL_MDMA_BLOCK_TRANSFER) || \
+ ((__VALUE__) == LL_MDMA_REPEAT_BLOCK_TRANSFER) || \
+ ((__VALUE__) == LL_MDMA_FULL_TRANSFER))
+
+#define IS_LL_MDMA_PADDINGALIGNEMENT(__VALUE__) (((__VALUE__) == LL_MDMA_DATAALIGN_RIGHT) || \
+ ((__VALUE__) == LL_MDMA_DATAALIGN_RIGHT_SIGNED) || \
+ ((__VALUE__) == LL_MDMA_DATAALIGN_LEFT))
+
+#define IS_LL_MDMA_PACKMODE(__VALUE__) (((__VALUE__) == LL_MDMA_PACK_DISABLE) || \
+ ((__VALUE__) == LL_MDMA_PACK_ENABLE))
+
+#define IS_LL_MDMA_BUFFER_XFERLENGTH(__VALUE__) ((__VALUE__) <= 0x0000007FU)
+
+#define IS_LL_MDMA_DESTBURST(__VALUE__) (((__VALUE__) == LL_MDMA_DEST_BURST_SINGLE) || \
+ ((__VALUE__) == LL_MDMA_DEST_BURST_2BEATS) || \
+ ((__VALUE__) == LL_MDMA_DEST_BURST_4BEATS) || \
+ ((__VALUE__) == LL_MDMA_DEST_BURST_8BEATS) || \
+ ((__VALUE__) == LL_MDMA_DEST_BURST_16BEATS)|| \
+ ((__VALUE__) == LL_MDMA_DEST_BURST_32BEATS)|| \
+ ((__VALUE__) == LL_MDMA_DEST_BURST_64BEATS)|| \
+ ((__VALUE__) == LL_MDMA_DEST_BURST_128BEATS))
+
+#define IS_LL_MDMA_SRCTBURST(__VALUE__) (((__VALUE__) == LL_MDMA_SRC_BURST_SINGLE) || \
+ ((__VALUE__) == LL_MDMA_SRC_BURST_2BEATS) || \
+ ((__VALUE__) == LL_MDMA_SRC_BURST_4BEATS) || \
+ ((__VALUE__) == LL_MDMA_SRC_BURST_8BEATS) || \
+ ((__VALUE__) == LL_MDMA_SRC_BURST_16BEATS)|| \
+ ((__VALUE__) == LL_MDMA_SRC_BURST_32BEATS)|| \
+ ((__VALUE__) == LL_MDMA_SRC_BURST_64BEATS)|| \
+ ((__VALUE__) == LL_MDMA_SRC_BURST_128BEATS))
+
+#define IS_LL_MDMA_DESTINCSIZE(__VALUE__) (((__VALUE__) == LL_MDMA_DEST_INC_OFFSET_BYTE) || \
+ ((__VALUE__) == LL_MDMA_DEST_INC_OFFSET_HALFWORD) || \
+ ((__VALUE__) == LL_MDMA_DEST_INC_OFFSET_WORD) || \
+ ((__VALUE__) == LL_MDMA_DEST_INC_OFFSET_DOUBLEWORD))
+
+#define IS_LL_MDMA_SRCINCSIZE(__VALUE__) (((__VALUE__) == LL_MDMA_SRC_INC_OFFSET_BYTE) || \
+ ((__VALUE__) == LL_MDMA_SRC_INC_OFFSET_HALFWORD) || \
+ ((__VALUE__) == LL_MDMA_SRC_INC_OFFSET_WORD) || \
+ ((__VALUE__) == LL_MDMA_SRC_INC_OFFSET_DOUBLEWORD))
+
+#define IS_LL_MDMA_DESTDATASIZE(__VALUE__) (((__VALUE__) == LL_MDMA_DEST_DATA_SIZE_BYTE) || \
+ ((__VALUE__) == LL_MDMA_DEST_DATA_SIZE_HALFWORD) || \
+ ((__VALUE__) == LL_MDMA_DEST_DATA_SIZE_WORD) || \
+ ((__VALUE__) == LL_MDMA_DEST_DATA_SIZE_DOUBLEWORD))
+
+#define IS_LL_MDMA_SRCDATASIZE(__VALUE__) (((__VALUE__) == LL_MDMA_SRC_DATA_SIZE_BYTE) || \
+ ((__VALUE__) == LL_MDMA_SRC_DATA_SIZE_HALFWORD) || \
+ ((__VALUE__) == LL_MDMA_SRC_DATA_SIZE_WORD) || \
+ ((__VALUE__) == LL_MDMA_SRC_DATA_SIZE_DOUBLEWORD))
+
+#define IS_LL_MDMA_DESTINCMODE(__VALUE__) (((__VALUE__) == LL_MDMA_DEST_FIXED) || \
+ ((__VALUE__) == LL_MDMA_DEST_INCREMENT) || \
+ ((__VALUE__) == LL_MDMA_DEST_DECREMENT))
+
+#define IS_LL_MDMA_SRCINCMODE(__VALUE__) (((__VALUE__) == LL_MDMA_SRC_FIXED) || \
+ ((__VALUE__) == LL_MDMA_SRC_INCREMENT) || \
+ ((__VALUE__) == LL_MDMA_SRC_DECREMENT))
+
+#define IS_LL_MDMA_BLKRPT_DEST_ADDRUPDATEMODE(__VALUE__) (((__VALUE__) == LL_MDMA_BLK_RPT_DEST_ADDR_INCREMENT) || \
+ ((__VALUE__) == LL_MDMA_BLK_RPT_DEST_ADDR_DECREMENT))
+
+
+#define IS_LL_MDMA_BLKRPT_SRC_ADDRUPDATEMODE(__VALUE__) (((__VALUE__) == LL_MDMA_BLK_RPT_SRC_ADDR_INCREMENT) || \
+ ((__VALUE__) == LL_MDMA_BLK_RPT_SRC_ADDR_DECREMENT))
+
+#define IS_LL_MDMA_BLKRPT_DEST_ADDRUPDATEVAL(__VALUE__) ((__VALUE__) <= 0x0000FFFFU)
+
+#define IS_LL_MDMA_BLKRPT_SRC_ADDRUPDATEVAL(__VALUE__) ((__VALUE__) <= 0x0000FFFFU)
+
+#define IS_LL_MDMA_DEST_BUS(__VALUE__) (((__VALUE__) == LL_MDMA_DEST_BUS_SYSTEM_AXI) || \
+ ((__VALUE__) == LL_MDMA_DEST_BUS_AHB_TCM))
+
+#define IS_LL_MDMA_SRC_BUS(__VALUE__) (((__VALUE__) == LL_MDMA_SRC_BUS_SYSTEM_AXI) || \
+ ((__VALUE__) == LL_MDMA_SRC_BUS_AHB_TCM))
+#if defined (QUADSPI) && defined (JPEG) && defined (DSI) /* STM32H747/57 devices */
+#define IS_LL_MDMA_HWTRIGGER(__VALUE__) (((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM0_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM1_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM2_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM3_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM4_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM5_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM6_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM7_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM0_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM1_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM2_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM3_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM4_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM5_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM6_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM7_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_LTDC_LINE_IT) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_INFIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_INFIFO_NF) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_OUTFIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_OUTFIFO_NE) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_END_CONVERSION) || \
+ ((__VALUE__) == LL_MDMA_REQ_QUADSPI_FIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_QUADSPI_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_CLUT_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_TW) || \
+ ((__VALUE__) == LL_MDMA_REQ_DSI_TEARING_EFFECT) || \
+ ((__VALUE__) == LL_MDMA_REQ_DSI_END_REFRESH) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_END_DATA) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_DMA_ENDBUFFER) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_COMMAND_END))
+#elif defined (QUADSPI) && defined (JPEG) /* STM32H743/53/45/55 devices */
+#define IS_LL_MDMA_HWTRIGGER(__VALUE__) (((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM0_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM1_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM2_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM3_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM4_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM5_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM6_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM7_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM0_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM1_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM2_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM3_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM4_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM5_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM6_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM7_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_LTDC_LINE_IT) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_INFIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_INFIFO_NF) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_OUTFIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_OUTFIFO_NE) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_END_CONVERSION) || \
+ ((__VALUE__) == LL_MDMA_REQ_QUADSPI_FIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_QUADSPI_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_CLUT_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_TW) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_END_DATA) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_DMA_ENDBUFFER) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_COMMAND_END))
+#elif defined (QUADSPI) /* STM32H742 devices */
+#define IS_LL_MDMA_HWTRIGGER(__VALUE__) (((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM0_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM1_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM2_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM3_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM4_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM5_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM6_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM7_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM0_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM1_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM2_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM3_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM4_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM5_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM6_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM7_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_QUADSPI_FIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_QUADSPI_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_CLUT_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_TW) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_END_DATA) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_DMA_ENDBUFFER) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_COMMAND_END))
+
+#else /* STM32H7A3/B3 devices */
+#define IS_LL_MDMA_HWTRIGGER(__VALUE__) (((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM0_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM1_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM2_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM3_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM4_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM5_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM6_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA1_STREAM7_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM0_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM1_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM2_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM3_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM4_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM5_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM6_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2_STREAM7_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_LTDC_LINE_IT) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_INFIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_INFIFO_NF) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_OUTFIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_OUTFIFO_NE) || \
+ ((__VALUE__) == LL_MDMA_REQ_JPEG_END_CONVERSION) || \
+ ((__VALUE__) == LL_MDMA_REQ_OCTOSPI1_FIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_OCTOSPI1_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_CLUT_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_TC) || \
+ ((__VALUE__) == LL_MDMA_REQ_DMA2D_TW) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_END_DATA) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_DMA_ENDBUFFER) || \
+ ((__VALUE__) == LL_MDMA_REQ_SDMMC1_COMMAND_END) || \
+ ((__VALUE__) == LL_MDMA_REQ_OCTOSPI2_FIFO_TH) || \
+ ((__VALUE__) == LL_MDMA_REQ_OCTOSPI2_TC))
+
+#endif /* QUADSPI && JPEG && DSI */
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup MDMA_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup MDMA_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize the MDMA registers to their default reset values.
+ * @param MDMAx MDMAx Instance
+ * @param Channel This parameter can be one of the following values:
+ * @arg @ref LL_MDMA_CHANNEL_0
+ * @arg @ref LL_MDMA_CHANNEL_1
+ * @arg @ref LL_MDMA_CHANNEL_2
+ * @arg @ref LL_MDMA_CHANNEL_3
+ * @arg @ref LL_MDMA_CHANNEL_4
+ * @arg @ref LL_MDMA_CHANNEL_5
+ * @arg @ref LL_MDMA_CHANNEL_6
+ * @arg @ref LL_MDMA_CHANNEL_7
+ * @arg @ref LL_MDMA_CHANNEL_8
+ * @arg @ref LL_MDMA_CHANNEL_9
+ * @arg @ref LL_MDMA_CHANNEL_10
+ * @arg @ref LL_MDMA_CHANNEL_11
+ * @arg @ref LL_MDMA_CHANNEL_12
+ * @arg @ref LL_MDMA_CHANNEL_13
+ * @arg @ref LL_MDMA_CHANNEL_14
+ * @arg @ref LL_MDMA_CHANNEL_15
+ * @arg @ref LL_MDMA_CHANNEL_ALL
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: MDMA registers are de-initialized
+ * - ERROR: Not applicable
+ */
+uint32_t LL_MDMA_DeInit(MDMA_TypeDef *MDMAx, uint32_t Channel)
+{
+ MDMA_Channel_TypeDef *tmp;
+ ErrorStatus status = SUCCESS;
+
+ /* Check the MDMA Instance MDMAx and Channel parameters*/
+ assert_param(IS_LL_MDMA_ALL_CHANNEL_INSTANCE(MDMAx, Channel));
+
+ if (Channel == LL_MDMA_CHANNEL_ALL)
+ {
+ LL_AHB3_GRP1_ForceReset(LL_AHB3_GRP1_PERIPH_MDMA);
+ LL_AHB3_GRP1_ReleaseReset(LL_AHB3_GRP1_PERIPH_MDMA);
+ }
+ else
+ {
+ /* Disable the selected Channel */
+ LL_MDMA_DisableChannel(MDMAx,Channel);
+
+ /* Get the MDMA Channel Instance */
+ tmp = (MDMA_Channel_TypeDef *)(LL_MDMA_GET_CHANNEL_INSTANCE(MDMAx, Channel));
+
+ /* Reset MDMAx_Channely control register */
+ LL_MDMA_WriteReg(tmp, CCR, 0U);
+
+ /* Reset MDMAx_Channely Configuration register */
+ LL_MDMA_WriteReg(tmp, CTCR, 0U);
+
+ /* Reset MDMAx_Channely block number of data register */
+ LL_MDMA_WriteReg(tmp, CBNDTR, 0U);
+
+ /* Reset MDMAx_Channely source address register */
+ LL_MDMA_WriteReg(tmp, CSAR, 0U);
+
+ /* Reset MDMAx_Channely destination address register */
+ LL_MDMA_WriteReg(tmp, CDAR, 0U);
+
+ /* Reset MDMAx_Channely Block Repeat address Update register */
+ LL_MDMA_WriteReg(tmp, CBRUR, 0U);
+
+ /* Reset MDMAx_Channely Link Address register */
+ LL_MDMA_WriteReg(tmp, CLAR, 0U);
+
+ /* Reset MDMAx_Channely Trigger and Bus selection register */
+ LL_MDMA_WriteReg(tmp, CTBR, 0U);
+
+ /* Reset MDMAx_Channely Mask address register */
+ LL_MDMA_WriteReg(tmp, CMAR, 0U);
+
+ /* Reset MDMAx_Channely Mask Data register */
+ LL_MDMA_WriteReg(tmp, CMDR, 0U);
+
+ /* Reset the Channel pending flags */
+ LL_MDMA_WriteReg(tmp, CIFCR, 0x0000001FU);
+ }
+
+ return (uint32_t)status;
+}
+
+/**
+ * @brief Initialize the MDMA registers according to the specified parameters in MDMA_InitStruct.
+ * @note To convert MDMAx_Channely Instance to MDMAx Instance and Channely, use helper macros :
+ * @arg @ref LL_MDMA_GET_INSTANCE
+ * @arg @ref LL_MDMA_GET_CHANNEL
+ * @param MDMAx MDMAx Instance
+ * @param Channel This parameter can be one of the following values:
+ * @arg @ref LL_MDMA_CHANNEL_0
+ * @arg @ref LL_MDMA_CHANNEL_1
+ * @arg @ref LL_MDMA_CHANNEL_2
+ * @arg @ref LL_MDMA_CHANNEL_3
+ * @arg @ref LL_MDMA_CHANNEL_4
+ * @arg @ref LL_MDMA_CHANNEL_5
+ * @arg @ref LL_MDMA_CHANNEL_6
+ * @arg @ref LL_MDMA_CHANNEL_7
+ * @arg @ref LL_MDMA_CHANNEL_8
+ * @arg @ref LL_MDMA_CHANNEL_9
+ * @arg @ref LL_MDMA_CHANNEL_10
+ * @arg @ref LL_MDMA_CHANNEL_11
+ * @arg @ref LL_MDMA_CHANNEL_12
+ * @arg @ref LL_MDMA_CHANNEL_13
+ * @arg @ref LL_MDMA_CHANNEL_14
+ * @arg @ref LL_MDMA_CHANNEL_15
+ * @param MDMA_InitStruct pointer to a @ref LL_MDMA_InitTypeDef structure.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: MDMA registers are initialized
+ * - ERROR: Not applicable
+ */
+uint32_t LL_MDMA_Init(MDMA_TypeDef *MDMAx, uint32_t Channel, LL_MDMA_InitTypeDef *MDMA_InitStruct)
+{
+ /* Check the MDMA Instance MDMAx and Channel parameters*/
+ assert_param(IS_LL_MDMA_ALL_CHANNEL_INSTANCE(MDMAx, Channel));
+
+ /* Check the MDMA parameters from MDMA_InitStruct */
+ assert_param(IS_LL_MDMA_BLK_DATALENGTH(MDMA_InitStruct->BlockDataLength));
+ assert_param(IS_LL_MDMA_BLK_REPEATCOUNT(MDMA_InitStruct->BlockRepeatCount));
+ assert_param(IS_LL_MDMA_WORDENDIANESS(MDMA_InitStruct->WordEndianess));
+ assert_param(IS_LL_MDMA_HALFWORDENDIANESS(MDMA_InitStruct->HalfWordEndianess));
+ assert_param(IS_LL_MDMA_BYTEENDIANESS(MDMA_InitStruct->ByteEndianess));
+ assert_param(IS_LL_MDMA_PRIORITY(MDMA_InitStruct->Priority));
+ assert_param(IS_LL_MDMA_BUFFWRITEMODE(MDMA_InitStruct->BufferableWriteMode));
+ assert_param(IS_LL_MDMA_REQUESTMODE(MDMA_InitStruct->RequestMode));
+ assert_param(IS_LL_MDMA_TRIGGERMODE(MDMA_InitStruct->TriggerMode));
+ assert_param(IS_LL_MDMA_PADDINGALIGNEMENT(MDMA_InitStruct->PaddingAlignment));
+ assert_param(IS_LL_MDMA_PACKMODE(MDMA_InitStruct->PackMode));
+ assert_param(IS_LL_MDMA_BUFFER_XFERLENGTH(MDMA_InitStruct->BufferTransferLength));
+ assert_param(IS_LL_MDMA_DESTBURST(MDMA_InitStruct->DestBurst));
+ assert_param(IS_LL_MDMA_SRCTBURST(MDMA_InitStruct->SrctBurst));
+ assert_param(IS_LL_MDMA_DESTINCSIZE(MDMA_InitStruct->DestIncSize));
+ assert_param(IS_LL_MDMA_SRCINCSIZE(MDMA_InitStruct->SrcIncSize));
+ assert_param(IS_LL_MDMA_DESTDATASIZE(MDMA_InitStruct->DestDataSize));
+ assert_param(IS_LL_MDMA_SRCDATASIZE(MDMA_InitStruct->SrcDataSize));
+ assert_param(IS_LL_MDMA_DESTINCMODE(MDMA_InitStruct->DestIncMode));
+ assert_param(IS_LL_MDMA_SRCINCMODE(MDMA_InitStruct->SrcIncMode));
+ assert_param(IS_LL_MDMA_BLKRPT_DEST_ADDRUPDATEMODE(MDMA_InitStruct->BlockRepeatDestAddrUpdateMode));
+ assert_param(IS_LL_MDMA_BLKRPT_SRC_ADDRUPDATEMODE(MDMA_InitStruct->BlockRepeatSrcAddrUpdateMode));
+ assert_param(IS_LL_MDMA_BLKRPT_DEST_ADDRUPDATEVAL(MDMA_InitStruct->BlockRepeatDestAddrUpdateVal));
+ assert_param(IS_LL_MDMA_BLKRPT_SRC_ADDRUPDATEVAL(MDMA_InitStruct->BlockRepeatSrcAddrUpdateVal));
+ assert_param(IS_LL_MDMA_DEST_BUS(MDMA_InitStruct->DestBus));
+ assert_param(IS_LL_MDMA_SRC_BUS(MDMA_InitStruct->SrcBus));
+ assert_param(IS_LL_MDMA_HWTRIGGER(MDMA_InitStruct->HWTrigger));
+
+
+ /*-------------------------- MDMAx CCR Configuration --------------------------
+ * Configure the Transfer endianness na priority with parameter :
+ * - WordEndianess: MDMA_CCR_WEX[14] bit
+ * - HalfWordEndianess: MDMA_CCR_HEX[13] bit
+ * - WordEndianess: MDMA_CCR_BEX[12] bit
+ * - Priority: MDMA_CCR_BEX[7:6] bits
+ */
+ LL_MDMA_ConfigXferEndianness(MDMAx, Channel, MDMA_InitStruct->WordEndianess | \
+ MDMA_InitStruct->HalfWordEndianess | \
+ MDMA_InitStruct->ByteEndianess);
+
+ LL_MDMA_SetChannelPriorityLevel(MDMAx, Channel, MDMA_InitStruct->Priority);
+
+ /*-------------------------- MDMAx CTCR Configuration --------------------------
+ * Configure the Transfer parameter :
+ * - BufferableWriteMode: MDMA_CTCR_BWM[31] bit
+ * - RequestMode: MDMA_CTCR_SWRM[30] bit
+ * - TriggerMode: MDMA_CTCR_TRGM[29:28] bits
+ * - PaddingAlignment: MDMA_CTCR_PAM[27:26] bits
+ * - PackMode: MDMA_CTCR_PKE[25] bit
+ * - BufferTransferLength: MDMA_CTCR_TLEN[24:18] bits
+ * - DestBurst: MDMA_CTCR_DBURST[17:15] bits
+ * - SrctBurst: MDMA_CTCR_SBURST[14:12] bits
+ * - DestIncSize: MDMA_CTCR_DINCOS[11:10] bits
+ * - SrcIncSize: MDMA_CTCR_SINCOS[9:8] bits
+ * - DestDataSize: MDMA_CTCR_DSIZE[7:6] bits
+ * - SrcDataSize: MDMA_CTCR_SSIZE[5:4] bits
+ * - DestIncMode: MDMA_CTCR_DINC[3:2] bits
+ * - SrcIncMode: MDMA_CTCR_SINC[1:0] bits
+ */
+ LL_MDMA_ConfigTransfer(MDMAx, Channel, MDMA_InitStruct->BufferableWriteMode | \
+ MDMA_InitStruct->RequestMode | \
+ MDMA_InitStruct->TriggerMode | \
+ MDMA_InitStruct->PaddingAlignment | \
+ MDMA_InitStruct->PackMode | \
+ MDMA_InitStruct->DestBurst | \
+ MDMA_InitStruct->SrctBurst | \
+ MDMA_InitStruct->DestIncSize | \
+ MDMA_InitStruct->SrcIncSize | \
+ MDMA_InitStruct->DestDataSize | \
+ MDMA_InitStruct->SrcDataSize | \
+ MDMA_InitStruct->DestIncMode | \
+ MDMA_InitStruct->SrcIncMode, MDMA_InitStruct->BufferTransferLength);
+
+ /*-------------------------- MDMAx CBNDTR Configuration --------------------------
+ * Configure the Transfer Block counters and update mode with parameter :
+ * - BlockRepeatCount: MDMA_CBNDTR_BRC[31:20] bits
+ * - BlockDataLength: MDMA_CBNDTR_BNDT[16:0] bits
+ * - BlockRepeatDestAddrUpdateMode: MDMA_CBNDTR_BRDUM[19] bit
+ * - BlockRepeatDestAddrUpdateMode: MDMA_CBNDTR_BRSUM[18] bit
+ */
+ LL_MDMA_ConfigBlkCounters(MDMAx, Channel, MDMA_InitStruct->BlockRepeatCount, MDMA_InitStruct->BlockDataLength);
+
+ LL_MDMA_ConfigBlkRepeatAddrUpdate(MDMAx, Channel, MDMA_InitStruct->BlockRepeatDestAddrUpdateMode | \
+ MDMA_InitStruct->BlockRepeatSrcAddrUpdateMode);
+
+
+
+ /*-------------------------- MDMAx CSAR Configuration --------------------------
+ * Configure the Transfer source address with parameter :
+ * - SrcAddress: MDMA_CSAR_SAR[31:0] bits
+ */
+ LL_MDMA_SetSourceAddress(MDMAx, Channel, MDMA_InitStruct->SrcAddress);
+
+ /*-------------------------- MDMAx CDAR Configuration --------------------------
+ * Configure the Transfer destination address with parameter :
+ * - DstAddress: MDMA_CDAR_DAR[31:0] bits
+ */
+ LL_MDMA_SetDestinationAddress(MDMAx, Channel, MDMA_InitStruct->DstAddress);
+
+ /*-------------------------- MDMAx CBRUR Configuration --------------------------
+ * Configure the Transfer Block repeat address update value with parameter :
+ * - BlockRepeatDestAddrUpdateVal: MDMA_CBRUR_DUV[31:16] bits
+ * - BlockRepeatSrcAddrUpdateVal: MDMA_CBRUR_SUV[15:0] bits
+ */
+ LL_MDMA_ConfigBlkRptAddrUpdateValue(MDMAx, Channel, MDMA_InitStruct->BlockRepeatSrcAddrUpdateVal, \
+ MDMA_InitStruct->BlockRepeatDestAddrUpdateVal);
+
+ /*-------------------------- MDMAx CLAR Configuration --------------------------
+ * Configure the Transfer linked list address with parameter :
+ * - LinkAddress: MDMA_CLAR_LAR[31:0] bits
+ */
+ LL_MDMA_SetLinkAddress(MDMAx, Channel, MDMA_InitStruct->LinkAddress);
+
+ /*-------------------------- MDMAx CTBR Configuration --------------------------
+ * Configure the Transfer HW trigger and bus selection with parameter :
+ * - DestBus: MDMA_TBR_DBUS[17] bit
+ * - SrcBus: MDMA_TBR_SBUS[16] bit
+ * - HWTrigger: MDMA_TBR_TSEL[5:0] bits
+ */
+ LL_MDMA_ConfigBusSelection(MDMAx, Channel, MDMA_InitStruct->DestBus | MDMA_InitStruct->SrcBus);
+
+ LL_MDMA_SetHWTrigger(MDMAx, Channel, MDMA_InitStruct->HWTrigger);
+
+ /*-------------------------- MDMAx CMAR Configuration --------------------------
+ * Configure the mask address with parameter :
+ * - MaskAddress: MDMA_CMAR_MAR[31:0] bits
+ */
+ LL_MDMA_SetMaskAddress(MDMAx, Channel, MDMA_InitStruct->MaskAddress);
+
+ /*-------------------------- MDMAx CMDR Configuration --------------------------
+ * Configure the mask data with parameter :
+ * - MaskData: MDMA_CMDR_MDR[31:0] bits
+ */
+ LL_MDMA_SetMaskData(MDMAx, Channel, MDMA_InitStruct->MaskData);
+
+ return (uint32_t)SUCCESS;
+}
+
+/**
+ * @brief Set each @ref LL_MDMA_InitTypeDef field to default value.
+ * @param MDMA_InitStruct Pointer to a @ref LL_MDMA_InitTypeDef structure.
+ * @retval None
+ */
+void LL_MDMA_StructInit(LL_MDMA_InitTypeDef *MDMA_InitStruct)
+{
+ /* Set DMA_InitStruct fields to default values */
+ MDMA_InitStruct->SrcAddress = 0x00000000U;
+ MDMA_InitStruct->DstAddress = 0x00000000U;
+ MDMA_InitStruct->BlockDataLength = 0x00000000U;
+ MDMA_InitStruct->BlockRepeatCount = 0x00000000U;
+ MDMA_InitStruct->WordEndianess = LL_MDMA_WORD_ENDIANNESS_PRESERVE;
+ MDMA_InitStruct->HalfWordEndianess = LL_MDMA_HALFWORD_ENDIANNESS_PRESERVE;
+ MDMA_InitStruct->ByteEndianess = LL_MDMA_BYTE_ENDIANNESS_PRESERVE;
+ MDMA_InitStruct->Priority = LL_MDMA_PRIORITY_LOW;
+ MDMA_InitStruct->BufferableWriteMode = LL_MDMA_BUFF_WRITE_DISABLE;
+ MDMA_InitStruct->RequestMode = LL_MDMA_REQUEST_MODE_HW;
+ MDMA_InitStruct->TriggerMode = LL_MDMA_BUFFER_TRANSFER;
+ MDMA_InitStruct->PaddingAlignment = LL_MDMA_DATAALIGN_RIGHT;
+ MDMA_InitStruct->PackMode = LL_MDMA_PACK_DISABLE;
+ MDMA_InitStruct->BufferTransferLength = 0x00000000U;
+ MDMA_InitStruct->DestBurst = LL_MDMA_DEST_BURST_SINGLE;
+ MDMA_InitStruct->SrctBurst = LL_MDMA_SRC_BURST_SINGLE;
+ MDMA_InitStruct->DestIncSize = LL_MDMA_DEST_INC_OFFSET_BYTE;
+ MDMA_InitStruct->SrcIncSize = LL_MDMA_SRC_INC_OFFSET_BYTE;
+ MDMA_InitStruct->DestDataSize = LL_MDMA_DEST_DATA_SIZE_BYTE;
+ MDMA_InitStruct->SrcDataSize = LL_MDMA_SRC_DATA_SIZE_BYTE;
+ MDMA_InitStruct->DestIncMode = LL_MDMA_DEST_FIXED;
+ MDMA_InitStruct->SrcIncMode = LL_MDMA_SRC_FIXED;
+ MDMA_InitStruct->BlockRepeatDestAddrUpdateMode = LL_MDMA_BLK_RPT_DEST_ADDR_INCREMENT;
+ MDMA_InitStruct->BlockRepeatSrcAddrUpdateMode = LL_MDMA_BLK_RPT_SRC_ADDR_INCREMENT;
+ MDMA_InitStruct->BlockRepeatDestAddrUpdateVal = 0x00000000U;
+ MDMA_InitStruct->BlockRepeatSrcAddrUpdateVal = 0x00000000U;
+ MDMA_InitStruct->LinkAddress = 0x00000000U;
+ MDMA_InitStruct->DestBus = LL_MDMA_DEST_BUS_SYSTEM_AXI;
+ MDMA_InitStruct->SrcBus = LL_MDMA_SRC_BUS_SYSTEM_AXI;
+ MDMA_InitStruct->HWTrigger = LL_MDMA_REQ_DMA1_STREAM0_TC;
+ MDMA_InitStruct->MaskAddress = 0x00000000U;
+ MDMA_InitStruct->MaskData = 0x00000000U;
+}
+
+/**
+ * @brief Initializes MDMA linked list node according to the specified
+ * parameters in the MDMA_InitStruct.
+ * @param MDMA_InitStruct Pointer to a @ref LL_MDMA_InitTypeDef structure that contains
+ * linked list node registers configurations.
+ * @param pNode Pointer to linked list node to fill according to MDMA_InitStruct parameters.
+ * @retval None
+ */
+void LL_MDMA_CreateLinkNode(LL_MDMA_InitTypeDef *MDMA_InitStruct, LL_MDMA_LinkNodeTypeDef *pNode)
+{
+
+ /* Check the MDMA parameters from MDMA_InitStruct */
+ assert_param(IS_LL_MDMA_BLK_DATALENGTH(MDMA_InitStruct->BlockDataLength));
+ assert_param(IS_LL_MDMA_BLK_REPEATCOUNT(MDMA_InitStruct->BlockRepeatCount));
+
+ assert_param(IS_LL_MDMA_BUFFWRITEMODE(MDMA_InitStruct->BufferableWriteMode));
+ assert_param(IS_LL_MDMA_REQUESTMODE(MDMA_InitStruct->RequestMode));
+ assert_param(IS_LL_MDMA_TRIGGERMODE(MDMA_InitStruct->TriggerMode));
+ assert_param(IS_LL_MDMA_PADDINGALIGNEMENT(MDMA_InitStruct->PaddingAlignment));
+ assert_param(IS_LL_MDMA_PACKMODE(MDMA_InitStruct->PackMode));
+ assert_param(IS_LL_MDMA_BUFFER_XFERLENGTH(MDMA_InitStruct->BufferTransferLength));
+ assert_param(IS_LL_MDMA_DESTBURST(MDMA_InitStruct->DestBurst));
+ assert_param(IS_LL_MDMA_SRCTBURST(MDMA_InitStruct->SrctBurst));
+ assert_param(IS_LL_MDMA_DESTINCSIZE(MDMA_InitStruct->DestIncSize));
+ assert_param(IS_LL_MDMA_SRCINCSIZE(MDMA_InitStruct->SrcIncSize));
+ assert_param(IS_LL_MDMA_DESTDATASIZE(MDMA_InitStruct->DestDataSize));
+ assert_param(IS_LL_MDMA_SRCDATASIZE(MDMA_InitStruct->SrcDataSize));
+ assert_param(IS_LL_MDMA_DESTINCMODE(MDMA_InitStruct->DestIncMode));
+ assert_param(IS_LL_MDMA_SRCINCMODE(MDMA_InitStruct->SrcIncMode));
+ assert_param(IS_LL_MDMA_BLKRPT_DEST_ADDRUPDATEMODE(MDMA_InitStruct->BlockRepeatDestAddrUpdateMode));
+ assert_param(IS_LL_MDMA_BLKRPT_SRC_ADDRUPDATEMODE(MDMA_InitStruct->BlockRepeatSrcAddrUpdateMode));
+ assert_param(IS_LL_MDMA_BLKRPT_DEST_ADDRUPDATEVAL(MDMA_InitStruct->BlockRepeatDestAddrUpdateVal));
+ assert_param(IS_LL_MDMA_BLKRPT_SRC_ADDRUPDATEVAL(MDMA_InitStruct->BlockRepeatSrcAddrUpdateVal));
+ assert_param(IS_LL_MDMA_DEST_BUS(MDMA_InitStruct->DestBus));
+ assert_param(IS_LL_MDMA_SRC_BUS(MDMA_InitStruct->SrcBus));
+ assert_param(IS_LL_MDMA_HWTRIGGER(MDMA_InitStruct->HWTrigger));
+
+
+ /*-------------------------- MDMAx CTCR Configuration --------------------------
+ * Configure the Transfer parameter :
+ * - BufferableWriteMode: MDMA_CTCR_BWM[31] bit
+ * - RequestMode: MDMA_CTCR_SWRM[30] bit
+ * - TriggerMode: MDMA_CTCR_TRGM[29:28] bits
+ * - PaddingAlignment: MDMA_CTCR_PAM[27:26] bits
+ * - PackMode: MDMA_CTCR_PKE[25] bit
+ * - BufferTransferLength: MDMA_CTCR_TLEN[24:18] bits
+ * - DestBurst: MDMA_CTCR_DBURST[17:15] bits
+ * - SrctBurst: MDMA_CTCR_SBURST[14:12] bits
+ * - DestIncSize: MDMA_CTCR_DINCOS[11:10] bits
+ * - SrcIncSize: MDMA_CTCR_SINCOS[9:8] bits
+ * - DestDataSize: MDMA_CTCR_DSIZE[7:6] bits
+ * - SrcDataSize: MDMA_CTCR_SSIZE[5:4] bits
+ * - DestIncMode: MDMA_CTCR_DINC[3:2] bits
+ * - SrcIncMode: MDMA_CTCR_SINC[1:0] bits
+ */
+ pNode->CTCR = MDMA_InitStruct->BufferableWriteMode | \
+ MDMA_InitStruct->RequestMode | \
+ MDMA_InitStruct->TriggerMode | \
+ MDMA_InitStruct->PaddingAlignment | \
+ MDMA_InitStruct->PackMode | \
+ MDMA_InitStruct->DestBurst | \
+ MDMA_InitStruct->SrctBurst | \
+ MDMA_InitStruct->DestIncSize | \
+ MDMA_InitStruct->SrcIncSize | \
+ MDMA_InitStruct->DestDataSize | \
+ MDMA_InitStruct->SrcDataSize | \
+ MDMA_InitStruct->DestIncMode | \
+ MDMA_InitStruct->SrcIncMode | \
+ ((MDMA_InitStruct->BufferTransferLength << MDMA_CTCR_TLEN_Pos) & MDMA_CTCR_TLEN_Msk);
+
+
+
+ /*-------------------------- MDMAx CBNDTR Configuration --------------------------
+ * Configure the Transfer Block counters and update mode with parameter :
+ * - BlockRepeatCount: MDMA_CBNDTR_BRC[31:20] bits
+ * - BlockDataLength: MDMA_CBNDTR_BNDT[16:0] bits
+ * - BlockRepeatDestAddrUpdateMode: MDMA_CBNDTR_BRDUM[19] bit
+ * - BlockRepeatDestAddrUpdateMode: MDMA_CBNDTR_BRSUM[18] bit
+ */
+ pNode->CBNDTR = ((MDMA_InitStruct->BlockRepeatCount << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC_Msk) | \
+ MDMA_InitStruct->BlockRepeatDestAddrUpdateMode | \
+ MDMA_InitStruct->BlockRepeatSrcAddrUpdateMode | \
+ (MDMA_InitStruct->BlockDataLength & MDMA_CBNDTR_BNDT_Msk);
+
+
+ /*-------------------------- MDMAx CSAR Configuration --------------------------
+ * Configure the Transfer source address with parameter :
+ * - SrcAddress: MDMA_CSAR_SAR[31:0] bits
+ */
+ pNode->CSAR = MDMA_InitStruct->SrcAddress;
+
+
+ /*-------------------------- MDMAx CDAR Configuration --------------------------
+ * Configure the Transfer destination address with parameter :
+ * - DstAddress: MDMA_CDAR_DAR[31:0] bits
+ */
+ pNode->CDAR = MDMA_InitStruct->DstAddress;
+
+ /*-------------------------- MDMAx CBRUR Configuration --------------------------
+ * Configure the Transfer Block repeat address update value with parameter :
+ * - BlockRepeatDestAddrUpdateVal: MDMA_CBRUR_DUV[31:16] bits
+ * - BlockRepeatSrcAddrUpdateVal: MDMA_CBRUR_SUV[15:0] bits
+ */
+ pNode->CBRUR = (MDMA_InitStruct->BlockRepeatSrcAddrUpdateVal & MDMA_CBRUR_SUV_Msk) | \
+ ((MDMA_InitStruct->BlockRepeatDestAddrUpdateVal << MDMA_CBRUR_DUV_Pos) & MDMA_CBRUR_DUV_Msk) ;
+
+ /*-------------------------- MDMAx CLAR Configuration --------------------------
+ * Configure the Transfer linked list address with parameter :
+ * - LinkAddress: MDMA_CLAR_LAR[31:0] bits
+ */
+ pNode->CLAR = MDMA_InitStruct->LinkAddress;
+
+ /*-------------------------- MDMAx CTBR Configuration --------------------------
+ * Configure the Transfer HW trigger and bus selection with parameter :
+ * - DestBus: MDMA_TBR_DBUS[17] bit
+ * - SrcBus: MDMA_TBR_SBUS[16] bit
+ * - HWTrigger: MDMA_TBR_TSEL[5:0] bits
+ */
+ pNode->CTBR = MDMA_InitStruct->DestBus | MDMA_InitStruct->SrcBus | MDMA_InitStruct->HWTrigger;
+
+ /*-------------------------- MDMAx CMAR Configuration --------------------------
+ * Configure the mask address with parameter :
+ * - MaskAddress: MDMA_CMAR_MAR[31:0] bits
+ */
+ pNode->CMAR = MDMA_InitStruct->MaskAddress;
+
+ /*-------------------------- MDMAx CMDR Configuration --------------------------
+ * Configure the mask data with parameter :
+ * - MaskData: MDMA_CMDR_MDR[31:0] bits
+ */
+ pNode->CMDR = MDMA_InitStruct->MaskData;
+
+
+ pNode->Reserved = 0;
+
+}
+
+/**
+ * @brief Connect Linked list Nodes.
+ * @param pPrevLinkNode Pointer to previous linked list node to be connected to new Lined list node.
+ * @param pNewLinkNode Pointer to new Linked list.
+ * @retval None
+ */
+void LL_MDMA_ConnectLinkNode(LL_MDMA_LinkNodeTypeDef *pPrevLinkNode, LL_MDMA_LinkNodeTypeDef *pNewLinkNode)
+{
+ pPrevLinkNode->CLAR = (uint32_t)pNewLinkNode;
+}
+
+/**
+ * @brief Disconnect the next linked list node.
+ * @param pLinkNode Pointer to linked list node to be disconnected from the next one.
+ * @retval None
+ */
+void LL_MDMA_DisconnectNextLinkNode(LL_MDMA_LinkNodeTypeDef *pLinkNode)
+{
+ pLinkNode->CLAR = 0;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* MDMA */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_opamp.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_opamp.c
new file mode 100644
index 0000000000..559da513f1
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_opamp.c
@@ -0,0 +1,230 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_opamp.c
+ * @author MCD Application Team
+ * @brief OPAMP LL module driver
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_opamp.h"
+
+#ifdef USE_FULL_ASSERT
+ #include "stm32_assert.h"
+#else
+ #define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (OPAMP1) || defined (OPAMP2)
+/** @addtogroup OPAMP_LL OPAMP
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+
+/** @addtogroup OPAMP_LL_Private_Macros
+ * @{
+ */
+
+/* Check of parameters for configuration of OPAMP hierarchical scope: */
+/* OPAMP instance. */
+
+#define IS_LL_OPAMP_POWER_MODE(__POWER_MODE__) \
+ ( ((__POWER_MODE__) == LL_OPAMP_POWERMODE_NORMAL) \
+ || ((__POWER_MODE__) == LL_OPAMP_POWERMODE_HIGHSPEED))
+
+#define IS_LL_OPAMP_FUNCTIONAL_MODE(__FUNCTIONAL_MODE__) \
+ ( ((__FUNCTIONAL_MODE__) == LL_OPAMP_MODE_STANDALONE) \
+ || ((__FUNCTIONAL_MODE__) == LL_OPAMP_MODE_FOLLOWER) \
+ || ((__FUNCTIONAL_MODE__) == LL_OPAMP_MODE_PGA) \
+ || ((__FUNCTIONAL_MODE__) == LL_OPAMP_MODE_PGA_IO0) \
+ || ((__FUNCTIONAL_MODE__) == LL_OPAMP_MODE_PGA_IO0_BIAS) \
+ || ((__FUNCTIONAL_MODE__) == LL_OPAMP_MODE_PGA_IO0_IO1_BIAS) \
+ )
+
+#if defined(DAC2)
+#define IS_LL_OPAMP_INPUT_NONINVERTING(__INPUT_NONINVERTING__) \
+ ( ((__INPUT_NONINVERTING__) == LL_OPAMP_INPUT_NONINVERT_IO0) \
+ || ((__INPUT_NONINVERTING__) == LL_OPAMP_INPUT_NONINVERT_DAC) \
+ || ((__INPUT_NONINVERTING__) == LL_OPAMP_INPUT_NONINVERT_DAC2) \
+ )
+#else
+#define IS_LL_OPAMP_INPUT_NONINVERTING(__INPUT_NONINVERTING__) \
+ ( ((__INPUT_NONINVERTING__) == LL_OPAMP_INPUT_NONINVERT_IO0) \
+ || ((__INPUT_NONINVERTING__) == LL_OPAMP_INPUT_NONINVERT_DAC) \
+ )
+#endif /* DAC2 */
+
+
+#define IS_LL_OPAMP_INPUT_INVERTING(__INPUT_INVERTING__) \
+ ( ((__INPUT_INVERTING__) == LL_OPAMP_INPUT_INVERT_IO0) \
+ || ((__INPUT_INVERTING__) == LL_OPAMP_INPUT_INVERT_IO1) \
+ || ((__INPUT_INVERTING__) == LL_OPAMP_INPUT_INVERT_CONNECT_NO) \
+ )
+
+/**
+ * @}
+ */
+
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup OPAMP_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup OPAMP_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize registers of the selected OPAMP instance
+ * to their default reset values.
+ * @note If comparator is locked, de-initialization by software is
+ * not possible.
+ * The only way to unlock the comparator is a device hardware reset.
+ * @param OPAMPx OPAMP instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: OPAMP registers are de-initialized
+ * - ERROR: OPAMP registers are not de-initialized
+ */
+ErrorStatus LL_OPAMP_DeInit(OPAMP_TypeDef* OPAMPx)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_OPAMP_ALL_INSTANCE(OPAMPx));
+
+ LL_OPAMP_WriteReg(OPAMPx, CSR, 0x00000000U);
+
+ return status;
+}
+
+/**
+ * @brief Initialize some features of OPAMP instance.
+ * @note This function reset bit of calibration mode to ensure
+ * to be in functional mode, in order to have OPAMP parameters
+ * (inputs selection, ...) set with the corresponding OPAMP mode
+ * to be effective.
+ * @param OPAMPx OPAMP instance
+ * @param OPAMP_InitStruct Pointer to a @ref LL_OPAMP_InitTypeDef structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: OPAMP registers are initialized
+ * - ERROR: OPAMP registers are not initialized
+ */
+ErrorStatus LL_OPAMP_Init(OPAMP_TypeDef *OPAMPx, LL_OPAMP_InitTypeDef *OPAMP_InitStruct)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_OPAMP_ALL_INSTANCE(OPAMPx));
+ assert_param(IS_LL_OPAMP_POWER_MODE(OPAMP_InitStruct->PowerMode));
+ assert_param(IS_LL_OPAMP_FUNCTIONAL_MODE(OPAMP_InitStruct->FunctionalMode));
+ assert_param(IS_LL_OPAMP_INPUT_NONINVERTING(OPAMP_InitStruct->InputNonInverting));
+
+ /* Note: OPAMP inverting input can be used with OPAMP in mode standalone */
+ /* or PGA with external capacitors for filtering circuit. */
+ /* Otherwise (OPAMP in mode follower), OPAMP inverting input is */
+ /* not used (not connected to GPIO pin). */
+ if(OPAMP_InitStruct->FunctionalMode != LL_OPAMP_MODE_FOLLOWER)
+ {
+ assert_param(IS_LL_OPAMP_INPUT_INVERTING(OPAMP_InitStruct->InputInverting));
+ }
+
+ /* Configuration of OPAMP instance : */
+ /* - PowerMode */
+ /* - Functional mode */
+ /* - Input non-inverting */
+ /* - Input inverting */
+ /* Note: Bit OPAMP_CSR_CALON reset to ensure to be in functional mode. */
+ if(OPAMP_InitStruct->FunctionalMode != LL_OPAMP_MODE_FOLLOWER)
+ {
+ MODIFY_REG(OPAMPx->CSR,
+ OPAMP_CSR_OPAHSM
+ | OPAMP_CSR_CALON
+ | OPAMP_CSR_VMSEL
+ | OPAMP_CSR_VPSEL
+ | OPAMP_CSR_PGGAIN_2 | OPAMP_CSR_PGGAIN_1
+ ,
+ (OPAMP_InitStruct->PowerMode & OPAMP_POWERMODE_CSR_BIT_MASK)
+ | OPAMP_InitStruct->FunctionalMode
+ | OPAMP_InitStruct->InputNonInverting
+ | OPAMP_InitStruct->InputInverting
+ );
+ }
+ else
+ {
+ MODIFY_REG(OPAMPx->CSR,
+ OPAMP_CSR_OPAHSM
+ | OPAMP_CSR_CALON
+ | OPAMP_CSR_VMSEL
+ | OPAMP_CSR_VPSEL
+ | OPAMP_CSR_PGGAIN_2 | OPAMP_CSR_PGGAIN_1
+ ,
+ (OPAMP_InitStruct->PowerMode & OPAMP_POWERMODE_CSR_BIT_MASK)
+ | LL_OPAMP_MODE_FOLLOWER
+ | OPAMP_InitStruct->InputNonInverting
+ );
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_OPAMP_InitTypeDef field to default value.
+ * @param OPAMP_InitStruct pointer to a @ref LL_OPAMP_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_OPAMP_StructInit(LL_OPAMP_InitTypeDef *OPAMP_InitStruct)
+{
+ /* Set OPAMP_InitStruct fields to default values */
+ OPAMP_InitStruct->PowerMode = LL_OPAMP_POWERMODE_NORMAL;
+ OPAMP_InitStruct->FunctionalMode = LL_OPAMP_MODE_FOLLOWER;
+ OPAMP_InitStruct->InputNonInverting = LL_OPAMP_INPUT_NONINVERT_IO0;
+ /* Note: Parameter discarded if OPAMP in functional mode follower, */
+ /* set anyway to its default value. */
+ OPAMP_InitStruct->InputInverting = LL_OPAMP_INPUT_INVERT_CONNECT_NO;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* OPAMP1 || OPAMP2 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_pwr.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_pwr.c
new file mode 100644
index 0000000000..194f52e339
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_pwr.c
@@ -0,0 +1,82 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_pwr.c
+ * @author MCD Application Team
+ * @brief PWR LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#if defined (USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_pwr.h"
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (PWR)
+
+/** @defgroup PWR_LL PWR
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup PWR_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup PWR_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize the PWR registers to their default reset values.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: PWR registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_PWR_DeInit(void)
+{
+ WRITE_REG(PWR->WKUPCR, (PWR_WKUPCR_WKUPC1 | PWR_WKUPCR_WKUPC2 | PWR_WKUPCR_WKUPC3 | \
+ PWR_WKUPCR_WKUPC4 | PWR_WKUPCR_WKUPC5 | PWR_WKUPCR_WKUPC6));
+
+ return SUCCESS;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+#endif /* defined (PWR) */
+/**
+ * @}
+ */
+
+#endif /* defined (USE_FULL_LL_DRIVER) */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_rcc.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_rcc.c
new file mode 100644
index 0000000000..699cd0ffe0
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_rcc.c
@@ -0,0 +1,1770 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_rcc.c
+ * @author MCD Application Team
+ * @brief RCC LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_rcc.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+ #include "stm32_assert.h"
+#else
+ #define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined(RCC)
+
+/** @addtogroup RCC_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+const uint8_t LL_RCC_PrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup RCC_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_RCC_USART_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USART16_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_USART234578_CLKSOURCE))
+
+
+#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2C123_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_I2C4_CLKSOURCE))
+
+#define IS_LL_RCC_LPTIM_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_LPTIM1_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_LPTIM2_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_LPTIM345_CLKSOURCE))
+
+#if defined(LL_RCC_SAI4A_CLKSOURCE)
+#define IS_LL_RCC_SAI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SAI1_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_SAI23_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_SAI4A_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_SAI4B_CLKSOURCE))
+#else
+#define IS_LL_RCC_SAI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SAI1_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_SAI2A_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_SAI2B_CLKSOURCE))
+#endif /* LL_RCC_SAI4A_CLKSOURCE */
+
+#define IS_LL_RCC_SPI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SPI123_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_SPI45_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_SPI6_CLKSOURCE))
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup RCC_LL_Private_Functions RCC Private functions
+ * @{
+ */
+uint32_t RCC_GetSystemClockFreq(void);
+uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency);
+uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency);
+uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency);
+uint32_t RCC_GetPCLK3ClockFreq(uint32_t HCLK_Frequency);
+uint32_t RCC_GetPCLK4ClockFreq(uint32_t HCLK_Frequency);
+
+/**
+ * @}
+ */
+
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup RCC_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup RCC_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @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 None
+ */
+void LL_RCC_DeInit(void)
+{
+ /* Set HSION bit */
+ SET_BIT(RCC->CR, RCC_CR_HSION);
+
+ /* Wait for HSI READY bit */
+ while(LL_RCC_HSI_IsReady() == 0U)
+ {}
+
+ /* Reset CFGR register */
+ CLEAR_REG(RCC->CFGR);
+
+ /* Reset CSION , CSIKERON, HSEON, HSI48ON, HSECSSON,HSIDIV, PLL1ON, PLL2ON, PLL3ON 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 | RCC_CR_PLL1ON | RCC_CR_PLL2ON | RCC_CR_PLL3ON);
+
+ /* Wait for PLL1 READY bit to be reset */
+ while(LL_RCC_PLL1_IsReady() != 0U)
+ {}
+
+ /* Wait for PLL2 READY bit to be reset */
+ while(LL_RCC_PLL2_IsReady() != 0U)
+ {}
+
+ /* Wait for PLL3 READY bit to be reset */
+ while(LL_RCC_PLL3_IsReady() != 0U)
+ {}
+
+#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 /* RCC_D1CFGR_HPRE */
+
+ /* 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 */
+ LL_RCC_WriteReg(PLLCFGR, 0x01FF0000U);
+
+ /* Reset PLL1DIVR register to default value */
+ LL_RCC_WriteReg(PLL1DIVR, 0x01010280U);
+
+ /* Reset PLL1FRACR register */
+ CLEAR_REG(RCC->PLL1FRACR);
+
+ /* Reset PLL2DIVR register to default value */
+ LL_RCC_WriteReg(PLL2DIVR, 0x01010280U);
+
+ /* Reset PLL2FRACR register */
+ CLEAR_REG(RCC->PLL2FRACR);
+
+ /* Reset PLL3DIVR register to default value */
+ LL_RCC_WriteReg(PLL3DIVR, 0x01010280U);
+
+ /* Reset PLL3FRACR register */
+ CLEAR_REG(RCC->PLL3FRACR);
+
+ /* Reset HSEBYP bit */
+ CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
+
+ /* Disable all interrupts */
+ CLEAR_REG(RCC->CIER);
+
+ /* Clear all interrupts */
+ SET_BIT(RCC->CICR, RCC_CICR_LSIRDYC | RCC_CICR_LSERDYC | RCC_CICR_HSIRDYC | RCC_CICR_HSERDYC
+ | RCC_CICR_CSIRDYC | RCC_CICR_HSI48RDYC | RCC_CICR_PLLRDYC | RCC_CICR_PLL2RDYC
+ | RCC_CICR_PLL3RDYC | RCC_CICR_LSECSSC | RCC_CICR_HSECSSC);
+
+ /* Clear reset source flags */
+ SET_BIT(RCC->RSR, RCC_RSR_RMVF);
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RCC_LL_EF_Get_Freq
+ * @brief Return the frequencies of different on chip clocks; System, AHB, APB1, APB2, APB3 and APB4 buses clocks.
+ * and different peripheral clocks available on the device.
+ * @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 CSI, function returns values based on CSI_VALUE(***)
+ * @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(**)
+ * or HSI_VALUE(*) multiplied/divided by the PLL factors.
+ * @note (*) HSI_VALUE is a constant defined in header file (default value
+ * 64 MHz) divider by HSIDIV, but the real value may vary depending on
+ * on the variations in voltage and temperature.
+ * @note (**) HSE_VALUE is a constant defined in header 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 (***) CSI_VALUE is a constant defined in header file (default value
+ * 4 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ * @note The result of this function could be incorrect when using fractional
+ * value for HSE crystal.
+ * @note This function can be used by the user application to compute the
+ * baud-rate for the communication peripherals or configure other parameters.
+ * @{
+ */
+
+/**
+ * @brief Return the frequencies of different on chip clocks; System, AHB, APB1, APB2, APB3 and APB4 buses clocks.
+ * @note Each time SYSCLK, HCLK, PCLK1, PCLK2, PCLK3 and/or PCLK4 clock changes, this function
+ * must be called to update structure fields. Otherwise, any
+ * configuration based on this function will be incorrect.
+ * @param RCC_Clocks pointer to a @ref LL_RCC_ClocksTypeDef structure which will hold the clocks frequencies
+ * @retval None
+ */
+void LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef *RCC_Clocks)
+{
+ /* Get SYSCLK frequency */
+ RCC_Clocks->SYSCLK_Frequency = RCC_GetSystemClockFreq();
+
+ /* HCLK clock frequency */
+ RCC_Clocks->HCLK_Frequency = RCC_GetHCLKClockFreq(RCC_Clocks->SYSCLK_Frequency);
+
+ /* PCLK1 clock frequency */
+ RCC_Clocks->PCLK1_Frequency = RCC_GetPCLK1ClockFreq(RCC_Clocks->HCLK_Frequency);
+
+ /* PCLK2 clock frequency */
+ RCC_Clocks->PCLK2_Frequency = RCC_GetPCLK2ClockFreq(RCC_Clocks->HCLK_Frequency);
+
+ /* PCLK3 clock frequency */
+ RCC_Clocks->PCLK3_Frequency = RCC_GetPCLK3ClockFreq(RCC_Clocks->HCLK_Frequency);
+
+ /* PCLK4 clock frequency */
+ RCC_Clocks->PCLK4_Frequency = RCC_GetPCLK4ClockFreq(RCC_Clocks->HCLK_Frequency);
+}
+
+/**
+ * @brief Return PLL1 clocks frequencies
+ * @note LL_RCC_PERIPH_FREQUENCY_NO returned for non activated output or oscillator not ready
+ * @retval None
+ */
+void LL_RCC_GetPLL1ClockFreq(LL_PLL_ClocksTypeDef *PLL_Clocks)
+{
+ uint32_t pllinputfreq = LL_RCC_PERIPH_FREQUENCY_NO, pllsource;
+ uint32_t m, n, fracn = 0U;
+
+ /* PLL_VCO = (HSE_VALUE, CSI_VALUE or HSI_VALUE/HSIDIV) / PLLM * (PLLN + FRACN)
+ SYSCLK = PLL_VCO / PLLP
+ */
+ pllsource = LL_RCC_PLL_GetSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ pllinputfreq = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ case LL_RCC_PLLSOURCE_CSI:
+ if (LL_RCC_CSI_IsReady() != 0U)
+ {
+ pllinputfreq = CSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE:
+ if (LL_RCC_HSE_IsReady() != 0U)
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_PLLSOURCE_NONE:
+ default:
+ /* PLL clock disabled */
+ break;
+ }
+
+ PLL_Clocks->PLL_P_Frequency = 0U;
+ PLL_Clocks->PLL_Q_Frequency = 0U;
+ PLL_Clocks->PLL_R_Frequency = 0U;
+
+ m = LL_RCC_PLL1_GetM();
+ n = LL_RCC_PLL1_GetN();
+ if (LL_RCC_PLL1FRACN_IsEnabled() != 0U)
+ {
+ fracn = LL_RCC_PLL1_GetFRACN();
+ }
+
+ if (m != 0U)
+ {
+ if (LL_RCC_PLL1P_IsEnabled() != 0U)
+ {
+ PLL_Clocks->PLL_P_Frequency = LL_RCC_CalcPLLClockFreq(pllinputfreq, m, n, fracn, LL_RCC_PLL1_GetP());
+ }
+
+ if (LL_RCC_PLL1Q_IsEnabled() != 0U)
+ {
+ PLL_Clocks->PLL_Q_Frequency = LL_RCC_CalcPLLClockFreq(pllinputfreq, m, n, fracn, LL_RCC_PLL1_GetQ());
+ }
+
+ if (LL_RCC_PLL1R_IsEnabled() != 0U)
+ {
+ PLL_Clocks->PLL_R_Frequency = LL_RCC_CalcPLLClockFreq(pllinputfreq, m, n, fracn, LL_RCC_PLL1_GetR());
+ }
+ }
+}
+
+/**
+ * @brief Return PLL2 clocks frequencies
+ * @note LL_RCC_PERIPH_FREQUENCY_NO returned for non activated output or oscillator not ready
+ * @retval None
+ */
+void LL_RCC_GetPLL2ClockFreq(LL_PLL_ClocksTypeDef *PLL_Clocks)
+{
+ uint32_t pllinputfreq = LL_RCC_PERIPH_FREQUENCY_NO, pllsource;
+ uint32_t m, n, fracn = 0U;
+
+ /* PLL_VCO = (HSE_VALUE, CSI_VALUE or HSI_VALUE/HSIDIV) / PLLM * (PLLN + FRACN)
+ SYSCLK = PLL_VCO / PLLP
+ */
+ pllsource = LL_RCC_PLL_GetSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ pllinputfreq = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ case LL_RCC_PLLSOURCE_CSI:
+ if (LL_RCC_CSI_IsReady() != 0U)
+ {
+ pllinputfreq = CSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE:
+ if (LL_RCC_HSE_IsReady() != 0U)
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_PLLSOURCE_NONE:
+ default:
+ /* PLL clock disabled */
+ break;
+ }
+
+ PLL_Clocks->PLL_P_Frequency = 0U;
+ PLL_Clocks->PLL_Q_Frequency = 0U;
+ PLL_Clocks->PLL_R_Frequency = 0U;
+
+ m = LL_RCC_PLL2_GetM();
+ n = LL_RCC_PLL2_GetN();
+ if (LL_RCC_PLL2FRACN_IsEnabled() != 0U)
+ {
+ fracn = LL_RCC_PLL2_GetFRACN();
+ }
+
+ if (m != 0U)
+ {
+ if (LL_RCC_PLL2P_IsEnabled() != 0U)
+ {
+ PLL_Clocks->PLL_P_Frequency = LL_RCC_CalcPLLClockFreq(pllinputfreq, m, n, fracn, LL_RCC_PLL2_GetP());
+ }
+
+ if (LL_RCC_PLL2Q_IsEnabled() != 0U)
+ {
+ PLL_Clocks->PLL_Q_Frequency = LL_RCC_CalcPLLClockFreq(pllinputfreq, m, n, fracn, LL_RCC_PLL2_GetQ());
+ }
+
+ if (LL_RCC_PLL2R_IsEnabled() != 0U)
+ {
+ PLL_Clocks->PLL_R_Frequency = LL_RCC_CalcPLLClockFreq(pllinputfreq, m, n, fracn, LL_RCC_PLL2_GetR());
+ }
+ }
+}
+
+/**
+ * @brief Return PLL3 clocks frequencies
+ * @note LL_RCC_PERIPH_FREQUENCY_NO returned for non activated output or oscillator not ready
+ * @retval None
+ */
+void LL_RCC_GetPLL3ClockFreq(LL_PLL_ClocksTypeDef *PLL_Clocks)
+{
+ uint32_t pllinputfreq = LL_RCC_PERIPH_FREQUENCY_NO, pllsource;
+ uint32_t m, n, fracn = 0U;
+
+ /* PLL_VCO = (HSE_VALUE, CSI_VALUE or HSI_VALUE/HSIDIV) / PLLM * (PLLN + FRACN)
+ SYSCLK = PLL_VCO / PLLP
+ */
+ pllsource = LL_RCC_PLL_GetSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ pllinputfreq = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ case LL_RCC_PLLSOURCE_CSI:
+ if (LL_RCC_CSI_IsReady() != 0U)
+ {
+ pllinputfreq = CSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE:
+ if (LL_RCC_HSE_IsReady() != 0U)
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_PLLSOURCE_NONE:
+ default:
+ /* PLL clock disabled */
+ break;
+ }
+
+ PLL_Clocks->PLL_P_Frequency = 0U;
+ PLL_Clocks->PLL_Q_Frequency = 0U;
+ PLL_Clocks->PLL_R_Frequency = 0U;
+
+ m = LL_RCC_PLL3_GetM();
+ n = LL_RCC_PLL3_GetN();
+ if (LL_RCC_PLL3FRACN_IsEnabled() != 0U)
+ {
+ fracn = LL_RCC_PLL3_GetFRACN();
+ }
+
+ if ((m != 0U) && (pllinputfreq != 0U))
+ {
+ if (LL_RCC_PLL3P_IsEnabled() != 0U)
+ {
+ PLL_Clocks->PLL_P_Frequency = LL_RCC_CalcPLLClockFreq(pllinputfreq, m, n, fracn, LL_RCC_PLL3_GetP());
+ }
+
+ if (LL_RCC_PLL3Q_IsEnabled() != 0U)
+ {
+ PLL_Clocks->PLL_Q_Frequency = LL_RCC_CalcPLLClockFreq(pllinputfreq, m, n, fracn, LL_RCC_PLL3_GetQ());
+ }
+
+ if (LL_RCC_PLL3R_IsEnabled() != 0U)
+ {
+ PLL_Clocks->PLL_R_Frequency = LL_RCC_CalcPLLClockFreq(pllinputfreq, m, n, fracn, LL_RCC_PLL3_GetR());
+ }
+ }
+}
+
+/**
+ * @brief Helper function to calculate the PLL frequency output
+ * @note ex: @ref LL_RCC_CalcPLLClockFreq (HSE_VALUE, @ref LL_RCC_PLL1_GetM (),
+ * @ref LL_RCC_PLL1_GetN (), @ref LL_RCC_PLL1_GetFRACN (), @ref LL_RCC_PLL1_GetP ());
+ * @param PLLInputFreq PLL Input frequency (based on HSE/(HSI/HSIDIV)/CSI)
+ * @param M Between 1 and 63
+ * @param N Between 4 and 512
+ * @param FRACN Between 0 and 0x1FFF
+ * @param PQR VCO output divider (P, Q or R)
+ * Between 1 and 128, except for PLL1P Odd value not allowed
+ * @retval PLL1 clock frequency (in Hz)
+ */
+uint32_t LL_RCC_CalcPLLClockFreq(uint32_t PLLInputFreq, uint32_t M, uint32_t N, uint32_t FRACN, uint32_t PQR)
+{
+ float_t freq;
+
+ freq = ((float_t)PLLInputFreq / (float_t)M) * ((float_t)N + ((float_t)FRACN/(float_t)0x2000));
+
+ freq = freq/(float_t)PQR;
+
+ return (uint32_t)freq;
+}
+
+/**
+ * @brief Return USARTx clock frequency
+ * @param USARTxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_USART16_CLKSOURCE
+ * @arg @ref LL_RCC_USART234578_CLKSOURCE
+ * @retval USART clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetUSARTClockFreq(uint32_t USARTxSource)
+{
+ uint32_t usart_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_USART_CLKSOURCE(USARTxSource));
+
+ switch (LL_RCC_GetUSARTClockSource(USARTxSource))
+ {
+ case LL_RCC_USART16_CLKSOURCE_PCLK2:
+ usart_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_USART234578_CLKSOURCE_PCLK1:
+ usart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_USART16_CLKSOURCE_PLL2Q:
+ case LL_RCC_USART234578_CLKSOURCE_PLL2Q:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ usart_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_USART16_CLKSOURCE_PLL3Q:
+ case LL_RCC_USART234578_CLKSOURCE_PLL3Q:
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ usart_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_USART16_CLKSOURCE_HSI:
+ case LL_RCC_USART234578_CLKSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ usart_frequency = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ case LL_RCC_USART16_CLKSOURCE_CSI:
+ case LL_RCC_USART234578_CLKSOURCE_CSI:
+ if (LL_RCC_CSI_IsReady() != 0U)
+ {
+ usart_frequency = CSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_USART16_CLKSOURCE_LSE:
+ case LL_RCC_USART234578_CLKSOURCE_LSE:
+ if (LL_RCC_LSE_IsReady() != 0U)
+ {
+ usart_frequency = LSE_VALUE;
+ }
+ break;
+
+ default:
+ /* Kernel clock disabled */
+ break;
+ }
+
+ return usart_frequency;
+}
+
+/**
+ * @brief Return LPUART clock frequency
+ * @param LPUARTxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_LPUART1_CLKSOURCE
+ * @retval LPUART clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetLPUARTClockFreq(uint32_t LPUARTxSource)
+{
+ uint32_t lpuart_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetLPUARTClockSource(LPUARTxSource))
+ {
+ case LL_RCC_LPUART1_CLKSOURCE_PCLK4:
+ lpuart_frequency = RCC_GetPCLK4ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_PLL2Q:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ lpuart_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_PLL3Q:
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ lpuart_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ lpuart_frequency = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_CSI:
+ if (LL_RCC_CSI_IsReady() != 0U)
+ {
+ lpuart_frequency = CSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_LSE:
+ if (LL_RCC_LSE_IsReady() != 0U)
+ {
+ lpuart_frequency = LSE_VALUE;
+ }
+ break;
+
+ default:
+ /* Kernel clock disabled */
+ break;
+ }
+
+ return lpuart_frequency;
+}
+
+/**
+ * @brief Return I2Cx clock frequency
+ * @param I2CxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_I2C123_CLKSOURCE
+ * @arg @ref LL_RCC_I2C4_CLKSOURCE
+ * @retval I2C clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetI2CClockFreq(uint32_t I2CxSource)
+{
+ uint32_t i2c_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_I2C_CLKSOURCE(I2CxSource));
+
+ switch (LL_RCC_GetI2CClockSource(I2CxSource))
+ {
+ case LL_RCC_I2C123_CLKSOURCE_PCLK1:
+ i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_I2C4_CLKSOURCE_PCLK4:
+ i2c_frequency = RCC_GetPCLK4ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_I2C123_CLKSOURCE_PLL3R:
+ case LL_RCC_I2C4_CLKSOURCE_PLL3R:
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ i2c_frequency = PLL_Clocks.PLL_R_Frequency;
+ }
+ break;
+
+ case LL_RCC_I2C123_CLKSOURCE_HSI:
+ case LL_RCC_I2C4_CLKSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ i2c_frequency = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ case LL_RCC_I2C123_CLKSOURCE_CSI:
+ case LL_RCC_I2C4_CLKSOURCE_CSI:
+ if (LL_RCC_CSI_IsReady() != 0U)
+ {
+ i2c_frequency = CSI_VALUE;
+ }
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return i2c_frequency;
+}
+
+/**
+ * @brief Return LPTIMx clock frequency
+ * @param LPTIMxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_LPTIM1_CLKSOURCE
+ * @arg @ref LL_RCC_LPTIM2_CLKSOURCE
+ * @arg @ref LL_RCC_LPTIM345_CLKSOURCE
+ * @retval LPTIM clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetLPTIMClockFreq(uint32_t LPTIMxSource)
+{
+ uint32_t lptim_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_LPTIM_CLKSOURCE(LPTIMxSource));
+
+ switch (LL_RCC_GetLPTIMClockSource(LPTIMxSource))
+ {
+ case LL_RCC_LPTIM1_CLKSOURCE_PCLK1:
+ lptim_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_LPTIM2_CLKSOURCE_PCLK4:
+ case LL_RCC_LPTIM345_CLKSOURCE_PCLK4:
+ lptim_frequency = RCC_GetPCLK4ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_LPTIM1_CLKSOURCE_PLL2P:
+ case LL_RCC_LPTIM2_CLKSOURCE_PLL2P:
+ case LL_RCC_LPTIM345_CLKSOURCE_PLL2P:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ lptim_frequency = PLL_Clocks.PLL_P_Frequency;
+ }
+ break;
+
+ case LL_RCC_LPTIM1_CLKSOURCE_PLL3R:
+ case LL_RCC_LPTIM2_CLKSOURCE_PLL3R:
+ case LL_RCC_LPTIM345_CLKSOURCE_PLL3R:
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ lptim_frequency = PLL_Clocks.PLL_R_Frequency;
+ }
+ break;
+
+ case LL_RCC_LPTIM1_CLKSOURCE_LSE:
+ case LL_RCC_LPTIM2_CLKSOURCE_LSE:
+ case LL_RCC_LPTIM345_CLKSOURCE_LSE:
+ if (LL_RCC_LSE_IsReady() != 0U)
+ {
+ lptim_frequency = LSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPTIM1_CLKSOURCE_LSI:
+ case LL_RCC_LPTIM2_CLKSOURCE_LSI:
+ case LL_RCC_LPTIM345_CLKSOURCE_LSI:
+ if (LL_RCC_LSI_IsReady() != 0U)
+ {
+ lptim_frequency = LSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPTIM1_CLKSOURCE_CLKP:
+ case LL_RCC_LPTIM2_CLKSOURCE_CLKP:
+ case LL_RCC_LPTIM345_CLKSOURCE_CLKP:
+ lptim_frequency = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE);
+ break;
+
+ default:
+ /* Kernel clock disabled */
+ break;
+ }
+
+ return lptim_frequency;
+}
+
+/**
+ * @brief Return SAIx clock frequency
+ * @param SAIxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_SAI1_CLKSOURCE
+ * @arg @ref LL_RCC_SAI23_CLKSOURCE (*)
+ * @arg @ref LL_RCC_SAI2A_CLKSOURCE (*)
+ * @arg @ref LL_RCC_SAI2B_CLKSOURCE (*)
+ * @arg @ref LL_RCC_SAI4A_CLKSOURCE (*)
+ * @arg @ref LL_RCC_SAI4B_CLKSOURCE (*)
+ * @retval SAI clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ *
+ * (*) : Available on some STM32H7 lines only.
+ */
+uint32_t LL_RCC_GetSAIClockFreq(uint32_t SAIxSource)
+{
+ uint32_t sai_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_SAI_CLKSOURCE(SAIxSource));
+
+ switch (LL_RCC_GetSAIClockSource(SAIxSource))
+ {
+ case LL_RCC_SAI1_CLKSOURCE_PLL1Q:
+#if defined(SAI3)
+ case LL_RCC_SAI23_CLKSOURCE_PLL1Q:
+#endif /* SAI3 */
+#if defined (RCC_CDCCIP1R_SAI2ASEL) || defined(RCC_CDCCIP1R_SAI2BSEL)
+ case LL_RCC_SAI2A_CLKSOURCE_PLL1Q:
+ case LL_RCC_SAI2B_CLKSOURCE_PLL1Q:
+#endif /* (RCC_CDCCIP1R_SAI2ASEL) || (RCC_CDCCIP1R_SAI2BSEL) */
+#if defined(SAI4_Block_A) || defined(SAI4_Block_B)
+ case LL_RCC_SAI4A_CLKSOURCE_PLL1Q:
+ case LL_RCC_SAI4B_CLKSOURCE_PLL1Q:
+#endif /* (SAI4_Block_A) || (SAI4_Block_B) */
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ sai_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_SAI1_CLKSOURCE_PLL2P:
+#if defined(SAI3)
+ case LL_RCC_SAI23_CLKSOURCE_PLL2P:
+#endif /* SAI3 */
+#if defined (RCC_CDCCIP1R_SAI2ASEL) || defined(RCC_CDCCIP1R_SAI2BSEL)
+ case LL_RCC_SAI2A_CLKSOURCE_PLL2P:
+ case LL_RCC_SAI2B_CLKSOURCE_PLL2P:
+#endif /* (RCC_CDCCIP1R_SAI2ASEL) || (RCC_CDCCIP1R_SAI2BSEL) */
+#if defined(SAI4_Block_A) || defined(SAI4_Block_B)
+ case LL_RCC_SAI4A_CLKSOURCE_PLL2P:
+ case LL_RCC_SAI4B_CLKSOURCE_PLL2P:
+#endif /* (SAI2_Block_A_BASE) || (SAI2_Block_B_BASE) */
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ sai_frequency = PLL_Clocks.PLL_P_Frequency;
+ }
+ break;
+
+ case LL_RCC_SAI1_CLKSOURCE_PLL3P:
+#if defined(SAI3)
+ case LL_RCC_SAI23_CLKSOURCE_PLL3P:
+#endif /* SAI3 */
+#if defined (RCC_CDCCIP1R_SAI2ASEL) || defined(RCC_CDCCIP1R_SAI2BSEL)
+ case LL_RCC_SAI2A_CLKSOURCE_PLL3P:
+ case LL_RCC_SAI2B_CLKSOURCE_PLL3P:
+#endif /* (RCC_CDCCIP1R_SAI2ASEL) || (RCC_CDCCIP1R_SAI2BSEL) */
+#if defined(SAI4_Block_A) || defined(SAI4_Block_B)
+ case LL_RCC_SAI4A_CLKSOURCE_PLL3P:
+ case LL_RCC_SAI4B_CLKSOURCE_PLL3P:
+#endif /* (SAI2_Block_A_BASE) || (SAI2_Block_B_BASE) */
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ sai_frequency = PLL_Clocks.PLL_P_Frequency;
+ }
+ break;
+
+ case LL_RCC_SAI1_CLKSOURCE_I2S_CKIN:
+#if defined(SAI3)
+ case LL_RCC_SAI23_CLKSOURCE_I2S_CKIN:
+#endif /* SAI3 */
+#if defined (RCC_CDCCIP1R_SAI2ASEL) || defined(RCC_CDCCIP1R_SAI2BSEL)
+ case LL_RCC_SAI2A_CLKSOURCE_I2S_CKIN:
+ case LL_RCC_SAI2B_CLKSOURCE_I2S_CKIN:
+#endif /* (RCC_CDCCIP1R_SAI2ASEL) || (RCC_CDCCIP1R_SAI2BSEL) */
+#if defined(SAI4_Block_A) || defined(SAI4_Block_B)
+ case LL_RCC_SAI4A_CLKSOURCE_I2S_CKIN:
+ case LL_RCC_SAI4B_CLKSOURCE_I2S_CKIN:
+#endif /* (SAI2_Block_A_BASE) || (SAI2_Block_B_BASE) */
+ sai_frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+
+ case LL_RCC_SAI1_CLKSOURCE_CLKP:
+#if defined(SAI3)
+ case LL_RCC_SAI23_CLKSOURCE_CLKP:
+#endif /* SAI3 */
+#if defined (RCC_CDCCIP1R_SAI2ASEL) || defined(RCC_CDCCIP1R_SAI2BSEL)
+ case LL_RCC_SAI2A_CLKSOURCE_CLKP:
+ case LL_RCC_SAI2B_CLKSOURCE_CLKP:
+#endif /* (RCC_CDCCIP1R_SAI2ASEL) || (RCC_CDCCIP1R_SAI2BSEL) */
+#if defined(SAI4_Block_A) || defined(SAI4_Block_B)
+ case LL_RCC_SAI4A_CLKSOURCE_CLKP:
+ case LL_RCC_SAI4B_CLKSOURCE_CLKP:
+#endif /* (SAI2_Block_A_BASE) || (SAI2_Block_B_BASE) */
+ sai_frequency = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE);
+ break;
+
+ default:
+ /* Kernel clock disabled */
+ break;
+ }
+
+ return sai_frequency;
+}
+
+/**
+ * @brief Return ADC clock frequency
+ * @param ADCxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_ADC_CLKSOURCE
+ * @retval ADC clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetADCClockFreq(uint32_t ADCxSource)
+{
+ uint32_t adc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetADCClockSource(ADCxSource))
+ {
+ case LL_RCC_ADC_CLKSOURCE_PLL2P:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ adc_frequency = PLL_Clocks.PLL_P_Frequency;
+ }
+ break;
+
+ case LL_RCC_ADC_CLKSOURCE_PLL3R:
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ adc_frequency = PLL_Clocks.PLL_R_Frequency;
+ }
+ break;
+
+ case LL_RCC_ADC_CLKSOURCE_CLKP:
+ adc_frequency = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE);
+ break;
+
+ default:
+ /* Kernel clock disabled */
+ break;
+ }
+
+ return adc_frequency;
+}
+
+/**
+ * @brief Return SDMMC clock frequency
+ * @param SDMMCxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_SDMMC_CLKSOURCE
+ * @retval SDMMC clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetSDMMCClockFreq(uint32_t SDMMCxSource)
+{
+ uint32_t sdmmc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetSDMMCClockSource(SDMMCxSource))
+ {
+ case LL_RCC_SDMMC_CLKSOURCE_PLL1Q:
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ sdmmc_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_SDMMC_CLKSOURCE_PLL2R:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ sdmmc_frequency = PLL_Clocks.PLL_R_Frequency;
+ }
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return sdmmc_frequency;
+}
+
+/**
+ * @brief Return RNG clock frequency
+ * @param RNGxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_RNG_CLKSOURCE
+ * @retval RNG clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetRNGClockFreq(uint32_t RNGxSource)
+{
+ uint32_t rng_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetRNGClockSource(RNGxSource))
+ {
+ case LL_RCC_RNG_CLKSOURCE_PLL1Q:
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ rng_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_RNG_CLKSOURCE_HSI48:
+ if (LL_RCC_HSI48_IsReady() != 0U)
+ {
+ rng_frequency = 48000000U;
+ }
+ break;
+
+ case LL_RCC_RNG_CLKSOURCE_LSE:
+ if (LL_RCC_LSE_IsReady() != 0U)
+ {
+ rng_frequency = LSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_RNG_CLKSOURCE_LSI:
+ if (LL_RCC_LSI_IsReady() != 0U)
+ {
+ rng_frequency = LSI_VALUE;
+ }
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return rng_frequency;
+}
+
+/**
+ * @brief Return CEC clock frequency
+ * @param CECxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_RNG_CLKSOURCE
+ * @retval CEC clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetCECClockFreq(uint32_t CECxSource)
+{
+ uint32_t cec_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ switch (LL_RCC_GetCECClockSource(CECxSource))
+ {
+ case LL_RCC_CEC_CLKSOURCE_LSE:
+ if (LL_RCC_LSE_IsReady() != 0U)
+ {
+ cec_frequency = LSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_CEC_CLKSOURCE_LSI:
+ if (LL_RCC_LSI_IsReady() != 0U)
+ {
+ cec_frequency = LSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_CEC_CLKSOURCE_CSI_DIV122:
+ if (LL_RCC_CSI_IsReady() != 0U)
+ {
+ cec_frequency = CSI_VALUE / 122U;
+ }
+ break;
+
+ default:
+ /* Kernel clock disabled */
+ break;
+ }
+
+ return cec_frequency;
+}
+
+/**
+ * @brief Return USB clock frequency
+ * @param USBxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_USB_CLKSOURCE
+ * @retval USB clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready or Disabled
+ */
+uint32_t LL_RCC_GetUSBClockFreq(uint32_t USBxSource)
+{
+ uint32_t usb_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetUSBClockSource(USBxSource))
+ {
+ case LL_RCC_USB_CLKSOURCE_PLL1Q:
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ usb_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_USB_CLKSOURCE_PLL3Q:
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ usb_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_USB_CLKSOURCE_HSI48:
+ if (LL_RCC_HSI48_IsReady() != 0U)
+ {
+ usb_frequency = HSI48_VALUE;
+ }
+ break;
+
+ case LL_RCC_USB_CLKSOURCE_DISABLE:
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return usb_frequency;
+}
+
+/**
+ * @brief Return DFSDM clock frequency
+ * @param DFSDMxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_DFSDM1_CLKSOURCE
+ * @retval DFSDM clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetDFSDMClockFreq(uint32_t DFSDMxSource)
+{
+ uint32_t dfsdm_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ switch (LL_RCC_GetDFSDMClockSource(DFSDMxSource))
+ {
+ case LL_RCC_DFSDM1_CLKSOURCE_SYSCLK:
+ dfsdm_frequency = RCC_GetSystemClockFreq();
+ break;
+
+ case LL_RCC_DFSDM1_CLKSOURCE_PCLK2:
+ dfsdm_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return dfsdm_frequency;
+}
+
+#if defined(DFSDM2_BASE)
+/**
+ * @brief Return DFSDM clock frequency
+ * @param DFSDMxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_DFSDM2_CLKSOURCE
+ * @retval DFSDM clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetDFSDM2ClockFreq(uint32_t DFSDMxSource)
+{
+ uint32_t dfsdm_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+
+ switch (LL_RCC_GetDFSDM2ClockSource(DFSDMxSource))
+ {
+
+ case LL_RCC_DFSDM2_CLKSOURCE_SYSCLK:
+ dfsdm_frequency = RCC_GetSystemClockFreq();
+ break;
+
+ case LL_RCC_DFSDM2_CLKSOURCE_PCLK4:
+ dfsdm_frequency = RCC_GetPCLK4ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return dfsdm_frequency;
+}
+#endif /* DFSDM2_BASE */
+
+#if defined(DSI)
+/**
+ * @brief Return DSI clock frequency
+ * @param DSIxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_DSI_CLKSOURCE
+ * @retval DSI clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that external clock is used
+ */
+uint32_t LL_RCC_GetDSIClockFreq(uint32_t DSIxSource)
+{
+ uint32_t dsi_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetDSIClockSource(DSIxSource))
+ {
+ case LL_RCC_DSI_CLKSOURCE_PLL2Q:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ dsi_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_DSI_CLKSOURCE_PHY:
+ dsi_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return dsi_frequency;
+}
+#endif /* DSI */
+
+/**
+ * @brief Return SPDIF clock frequency
+ * @param SPDIFxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_SPDIF_CLKSOURCE
+ * @retval SPDIF clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetSPDIFClockFreq(uint32_t SPDIFxSource)
+{
+ uint32_t spdif_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetSPDIFClockSource(SPDIFxSource))
+ {
+ case LL_RCC_SPDIF_CLKSOURCE_PLL1Q:
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ spdif_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_SPDIF_CLKSOURCE_PLL2R:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ spdif_frequency = PLL_Clocks.PLL_R_Frequency;
+ }
+ break;
+
+ case LL_RCC_SPDIF_CLKSOURCE_PLL3R:
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ spdif_frequency = PLL_Clocks.PLL_R_Frequency;
+ }
+ break;
+
+ case LL_RCC_SPDIF_CLKSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ spdif_frequency = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return spdif_frequency;
+}
+
+/**
+ * @brief Return SPIx clock frequency
+ * @param SPIxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_SPI123_CLKSOURCE
+ * @arg @ref LL_RCC_SPI45_CLKSOURCE
+ * @arg @ref LL_RCC_SPI6_CLKSOURCE
+ * @retval SPI clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetSPIClockFreq(uint32_t SPIxSource)
+{
+ uint32_t spi_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_SPI_CLKSOURCE(SPIxSource));
+
+ switch (LL_RCC_GetSPIClockSource(SPIxSource))
+ {
+ case LL_RCC_SPI123_CLKSOURCE_PLL1Q:
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ spi_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_SPI123_CLKSOURCE_PLL2P:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ spi_frequency = PLL_Clocks.PLL_P_Frequency;
+ }
+ break;
+
+ case LL_RCC_SPI123_CLKSOURCE_PLL3P:
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ spi_frequency = PLL_Clocks.PLL_P_Frequency;
+ }
+ break;
+
+ case LL_RCC_SPI123_CLKSOURCE_I2S_CKIN:
+#if defined(LL_RCC_SPI6_CLKSOURCE_I2S_CKIN)
+ case LL_RCC_SPI6_CLKSOURCE_I2S_CKIN:
+#endif /* LL_RCC_SPI6_CLKSOURCE_I2S_CKIN */
+ spi_frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+
+ case LL_RCC_SPI123_CLKSOURCE_CLKP:
+ spi_frequency = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE);
+ break;
+
+ case LL_RCC_SPI45_CLKSOURCE_PCLK2:
+ spi_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_SPI6_CLKSOURCE_PCLK4:
+ spi_frequency = RCC_GetPCLK4ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_SPI45_CLKSOURCE_PLL2Q:
+ case LL_RCC_SPI6_CLKSOURCE_PLL2Q:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ spi_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_SPI45_CLKSOURCE_PLL3Q:
+ case LL_RCC_SPI6_CLKSOURCE_PLL3Q:
+ if (LL_RCC_PLL3_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL3ClockFreq(&PLL_Clocks);
+ spi_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_SPI45_CLKSOURCE_HSI:
+ case LL_RCC_SPI6_CLKSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ spi_frequency = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ case LL_RCC_SPI45_CLKSOURCE_CSI:
+ case LL_RCC_SPI6_CLKSOURCE_CSI:
+ if (LL_RCC_CSI_IsReady() != 0U)
+ {
+ spi_frequency = CSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_SPI45_CLKSOURCE_HSE:
+ case LL_RCC_SPI6_CLKSOURCE_HSE:
+ if (LL_RCC_HSE_IsReady() != 0U)
+ {
+ spi_frequency = HSE_VALUE;
+ }
+ break;
+
+ default:
+ /* Kernel clock disabled */
+ break;
+ }
+
+ return spi_frequency;
+}
+
+/**
+ * @brief Return SWP clock frequency
+ * @param SWPxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_SWP_CLKSOURCE
+ * @retval SWP clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetSWPClockFreq(uint32_t SWPxSource)
+{
+ uint32_t swp_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ switch (LL_RCC_GetSWPClockSource(SWPxSource))
+ {
+ case LL_RCC_SWP_CLKSOURCE_PCLK1:
+ swp_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler())));
+ break;
+
+ case LL_RCC_SWP_CLKSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ swp_frequency = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return swp_frequency;
+}
+
+/**
+ * @brief Return FDCAN clock frequency
+ * @param FDCANxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_FDCAN_CLKSOURCE
+ * @retval FDCAN clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetFDCANClockFreq(uint32_t FDCANxSource)
+{
+ uint32_t fdcan_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetFDCANClockSource(FDCANxSource))
+ {
+ case LL_RCC_FDCAN_CLKSOURCE_HSE:
+ if (LL_RCC_HSE_IsReady() != 0U)
+ {
+ fdcan_frequency = HSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_FDCAN_CLKSOURCE_PLL1Q:
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ fdcan_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_FDCAN_CLKSOURCE_PLL2Q:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ fdcan_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ default:
+ /* Kernel clock disabled */
+ break;
+ }
+
+ return fdcan_frequency;
+}
+
+/**
+ * @brief Return FMC clock frequency
+ * @param FMCxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_FMC_CLKSOURCE
+ * @retval FMC clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetFMCClockFreq(uint32_t FMCxSource)
+{
+ uint32_t fmc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetFMCClockSource(FMCxSource))
+ {
+ case LL_RCC_FMC_CLKSOURCE_HCLK:
+ fmc_frequency = RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler()));
+ break;
+
+ case LL_RCC_FMC_CLKSOURCE_PLL1Q:
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ fmc_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_FMC_CLKSOURCE_PLL2R:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ fmc_frequency = PLL_Clocks.PLL_R_Frequency;
+ }
+ break;
+
+ case LL_RCC_FMC_CLKSOURCE_CLKP:
+ fmc_frequency = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE);
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return fmc_frequency;
+}
+
+#if defined(QUADSPI)
+/**
+ * @brief Return QSPI clock frequency
+ * @param QSPIxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_QSPI_CLKSOURCE
+ * @retval QSPI clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetQSPIClockFreq(uint32_t QSPIxSource)
+{
+ uint32_t qspi_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetQSPIClockSource(QSPIxSource))
+ {
+ case LL_RCC_QSPI_CLKSOURCE_HCLK:
+ qspi_frequency = RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler()));
+ break;
+
+ case LL_RCC_QSPI_CLKSOURCE_PLL1Q:
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ qspi_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_QSPI_CLKSOURCE_PLL2R:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ qspi_frequency = PLL_Clocks.PLL_R_Frequency;
+ }
+ break;
+
+ case LL_RCC_QSPI_CLKSOURCE_CLKP:
+ qspi_frequency = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE);
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return qspi_frequency;
+}
+#endif /* QUADSPI */
+
+#if defined(OCTOSPI1) || defined(OCTOSPI2)
+/**
+ * @brief Return OSPI clock frequency
+ * @param QSPIxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_OSPI_CLKSOURCE
+ * @retval OSPI clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+
+uint32_t LL_RCC_GetOSPIClockFreq(uint32_t OSPIxSource)
+{
+ uint32_t ospi_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ switch (LL_RCC_GetOSPIClockSource(OSPIxSource))
+ {
+ case LL_RCC_OSPI_CLKSOURCE_HCLK:
+ ospi_frequency = RCC_GetHCLKClockFreq(LL_RCC_CALC_SYSCLK_FREQ(RCC_GetSystemClockFreq(),LL_RCC_GetSysPrescaler()));
+ break;
+
+ case LL_RCC_OSPI_CLKSOURCE_PLL1Q:
+ if (LL_RCC_PLL1_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ ospi_frequency = PLL_Clocks.PLL_Q_Frequency;
+ }
+ break;
+
+ case LL_RCC_OSPI_CLKSOURCE_PLL2R:
+ if (LL_RCC_PLL2_IsReady() != 0U)
+ {
+ LL_RCC_GetPLL2ClockFreq(&PLL_Clocks);
+ ospi_frequency = PLL_Clocks.PLL_R_Frequency;
+ }
+ break;
+
+ case LL_RCC_OSPI_CLKSOURCE_CLKP:
+ ospi_frequency = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE);
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return ospi_frequency;
+}
+#endif /* defined(OCTOSPI1) || defined(OCTOSPI2) */
+
+/**
+ * @brief Return CLKP clock frequency
+ * @param CLKPxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_CLKP_CLKSOURCE
+ * @retval CLKP clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
+ */
+uint32_t LL_RCC_GetCLKPClockFreq(uint32_t CLKPxSource)
+{
+ uint32_t clkp_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ switch (LL_RCC_GetCLKPClockSource(CLKPxSource))
+ {
+ case LL_RCC_CLKP_CLKSOURCE_HSI:
+ if (LL_RCC_HSI_IsReady() != 0U)
+ {
+ clkp_frequency = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ }
+ break;
+
+ case LL_RCC_CLKP_CLKSOURCE_CSI:
+ if (LL_RCC_CSI_IsReady() != 0U)
+ {
+ clkp_frequency = CSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_CLKP_CLKSOURCE_HSE:
+ if (LL_RCC_HSE_IsReady() != 0U)
+ {
+ clkp_frequency = HSE_VALUE;
+ }
+ break;
+
+ default:
+ /* CLKP clock disabled */
+ break;
+ }
+
+ return clkp_frequency;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RCC_LL_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Return SYSTEM clock frequency
+ * @retval SYSTEM clock frequency (in Hz)
+ */
+uint32_t RCC_GetSystemClockFreq(void)
+{
+ uint32_t frequency = 0U;
+ LL_PLL_ClocksTypeDef PLL_Clocks;
+
+ /* Get SYSCLK source -------------------------------------------------------*/
+ switch (LL_RCC_GetSysClkSource())
+ {
+ /* No check on Ready: Won't be selected by hardware if not */
+ case LL_RCC_SYS_CLKSOURCE_STATUS_HSI:
+ frequency = HSI_VALUE >> (LL_RCC_HSI_GetDivider()>> RCC_CR_HSIDIV_Pos);
+ break;
+
+ case LL_RCC_SYS_CLKSOURCE_STATUS_CSI:
+ frequency = CSI_VALUE;
+ break;
+
+ case LL_RCC_SYS_CLKSOURCE_STATUS_HSE:
+ frequency = HSE_VALUE;
+ break;
+
+ case LL_RCC_SYS_CLKSOURCE_STATUS_PLL1:
+ LL_RCC_GetPLL1ClockFreq(&PLL_Clocks);
+ frequency = PLL_Clocks.PLL_P_Frequency;
+ break;
+
+ default:
+ /* Nothing to do */
+ break;
+ }
+
+ return frequency;
+}
+
+/**
+ * @brief Return HCLK clock frequency
+ * @param SYSCLK_Frequency SYSCLK clock frequency
+ * @retval HCLK clock frequency (in Hz)
+ */
+uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency)
+{
+ /* HCLK clock frequency */
+ return LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, LL_RCC_GetAHBPrescaler());
+}
+
+/**
+ * @brief Return PCLK1 clock frequency
+ * @param HCLK_Frequency HCLK clock frequency
+ * @retval PCLK1 clock frequency (in Hz)
+ */
+uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency)
+{
+ /* PCLK1 clock frequency */
+ return LL_RCC_CALC_PCLK1_FREQ(HCLK_Frequency, LL_RCC_GetAPB1Prescaler());
+}
+
+/**
+ * @brief Return PCLK2 clock frequency
+ * @param HCLK_Frequency HCLK clock frequency
+ * @retval PCLK2 clock frequency (in Hz)
+ */
+uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency)
+{
+ /* PCLK2 clock frequency */
+ return LL_RCC_CALC_PCLK2_FREQ(HCLK_Frequency, LL_RCC_GetAPB2Prescaler());
+}
+
+/**
+ * @brief Return PCLK3 clock frequency
+ * @param HCLK_Frequency HCLK clock frequency
+ * @retval PCLK3 clock frequency (in Hz)
+ */
+uint32_t RCC_GetPCLK3ClockFreq(uint32_t HCLK_Frequency)
+{
+ /* PCLK3 clock frequency */
+ return LL_RCC_CALC_PCLK3_FREQ(HCLK_Frequency, LL_RCC_GetAPB3Prescaler());
+}
+
+/**
+ * @brief Return PCLK4 clock frequency
+ * @param HCLK_Frequency HCLK clock frequency
+ * @retval PCLK4 clock frequency (in Hz)
+ */
+uint32_t RCC_GetPCLK4ClockFreq(uint32_t HCLK_Frequency)
+{
+ /* PCLK4 clock frequency */
+ return LL_RCC_CALC_PCLK4_FREQ(HCLK_Frequency, LL_RCC_GetAPB4Prescaler());
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined(RCC) */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_rng.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_rng.c
new file mode 100644
index 0000000000..8579270538
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_rng.c
@@ -0,0 +1,158 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_rng.c
+ * @author MCD Application Team
+ * @brief RNG LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_rng.h"
+#include "stm32h7xx_ll_bus.h"
+
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (RNG)
+
+/** @addtogroup RNG_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup RNG_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_RNG_CED(__MODE__) (((__MODE__) == LL_RNG_CED_ENABLE) || \
+ ((__MODE__) == LL_RNG_CED_DISABLE))
+
+#if defined(RNG_CR_CONDRST)
+#define IS_LL_RNG_CLOCK_DIVIDER(__CLOCK_DIV__) ((__CLOCK_DIV__) <=0x0Fu)
+
+
+#define IS_LL_RNG_NIST_COMPLIANCE(__NIST_COMPLIANCE__) (((__NIST_COMPLIANCE__) == LL_RNG_NIST_COMPLIANT) || \
+ ((__NIST_COMPLIANCE__) == LL_RNG_NOTNIST_COMPLIANT))
+
+#define IS_LL_RNG_CONFIG1 (__CONFIG1__) ((__CONFIG1__) <= 0x3FUL)
+
+#define IS_LL_RNG_CONFIG2 (__CONFIG2__) ((__CONFIG2__) <= 0x07UL)
+
+#define IS_LL_RNG_CONFIG3 (__CONFIG3__) ((__CONFIG3__) <= 0xFUL)
+#endif /* RNG_CR_CONDRST*/
+/**
+ * @}
+ */
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup RNG_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup RNG_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize RNG registers (Registers restored to their default values).
+ * @param RNGx RNG Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RNG registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_RNG_DeInit(RNG_TypeDef *RNGx)
+{
+ /* Check the parameters */
+ assert_param(IS_RNG_ALL_INSTANCE(RNGx));
+ /* Enable RNG reset state */
+ LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_RNG);
+
+ /* Release RNG from reset state */
+ LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_RNG);
+ return (SUCCESS);
+}
+
+/**
+ * @brief Initialize RNG registers according to the specified parameters in RNG_InitStruct.
+ * @param RNGx RNG Instance
+ * @param RNG_InitStruct pointer to a LL_RNG_InitTypeDef structure
+ * that contains the configuration information for the specified RNG peripheral.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RNG registers are initialized according to RNG_InitStruct content
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_RNG_Init(RNG_TypeDef *RNGx, LL_RNG_InitTypeDef *RNG_InitStruct)
+{
+ /* Check the parameters */
+ assert_param(IS_RNG_ALL_INSTANCE(RNGx));
+ assert_param(IS_LL_RNG_CED(RNG_InitStruct->ClockErrorDetection));
+
+#if defined(RNG_CR_CONDRST)
+ /* Clock Error Detection Configuration when CONDRT bit is set to 1 */
+ MODIFY_REG(RNGx->CR, RNG_CR_CED | RNG_CR_CONDRST, RNG_InitStruct->ClockErrorDetection | RNG_CR_CONDRST);
+ /* Writing bits CONDRST=0*/
+ CLEAR_BIT(RNGx->CR, RNG_CR_CONDRST);
+#else
+ /* Clock Error Detection configuration */
+ MODIFY_REG(RNGx->CR, RNG_CR_CED, RNG_InitStruct->ClockErrorDetection);
+#endif /* RNG_CR_CONDRST */
+
+ return (SUCCESS);
+}
+
+/**
+ * @brief Set each @ref LL_RNG_InitTypeDef field to default value.
+ * @param RNG_InitStruct pointer to a @ref LL_RNG_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_RNG_StructInit(LL_RNG_InitTypeDef *RNG_InitStruct)
+{
+ /* Set RNG_InitStruct fields to default values */
+ RNG_InitStruct->ClockErrorDetection = LL_RNG_CED_ENABLE;
+
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* RNG */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_rtc.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_rtc.c
new file mode 100644
index 0000000000..b7c23bc2b4
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_rtc.c
@@ -0,0 +1,894 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_rtc.c
+ * @author MCD Application Team
+ * @brief RTC LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_rtc.h"
+#include "stm32h7xx_ll_cortex.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined(RTC)
+
+/** @addtogroup RTC_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup RTC_LL_Private_Constants
+ * @{
+ */
+/* Default values used for prescaler */
+#define RTC_ASYNCH_PRESC_DEFAULT 0x0000007FU
+#define RTC_SYNCH_PRESC_DEFAULT 0x000000FFU
+
+/* Values used for timeout */
+#define RTC_INITMODE_TIMEOUT 1000U /* 1s when tick set to 1ms */
+#define RTC_SYNCHRO_TIMEOUT 1000U /* 1s when tick set to 1ms */
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup RTC_LL_Private_Macros
+ * @{
+ */
+
+#define IS_LL_RTC_HOURFORMAT(__VALUE__) (((__VALUE__) == LL_RTC_HOURFORMAT_24HOUR) \
+ || ((__VALUE__) == LL_RTC_HOURFORMAT_AMPM))
+
+#define IS_LL_RTC_ASYNCH_PREDIV(__VALUE__) ((__VALUE__) <= 0x7FU)
+
+#define IS_LL_RTC_SYNCH_PREDIV(__VALUE__) ((__VALUE__) <= 0x7FFFU)
+
+#define IS_LL_RTC_FORMAT(__VALUE__) (((__VALUE__) == LL_RTC_FORMAT_BIN) \
+ || ((__VALUE__) == LL_RTC_FORMAT_BCD))
+
+#define IS_LL_RTC_TIME_FORMAT(__VALUE__) (((__VALUE__) == LL_RTC_TIME_FORMAT_AM_OR_24) \
+ || ((__VALUE__) == LL_RTC_TIME_FORMAT_PM))
+
+#define IS_LL_RTC_HOUR12(__HOUR__) (((__HOUR__) > 0U) && ((__HOUR__) <= 12U))
+#define IS_LL_RTC_HOUR24(__HOUR__) ((__HOUR__) <= 23U)
+#define IS_LL_RTC_MINUTES(__MINUTES__) ((__MINUTES__) <= 59U)
+#define IS_LL_RTC_SECONDS(__SECONDS__) ((__SECONDS__) <= 59U)
+
+#define IS_LL_RTC_WEEKDAY(__VALUE__) (((__VALUE__) == LL_RTC_WEEKDAY_MONDAY) \
+ || ((__VALUE__) == LL_RTC_WEEKDAY_TUESDAY) \
+ || ((__VALUE__) == LL_RTC_WEEKDAY_WEDNESDAY) \
+ || ((__VALUE__) == LL_RTC_WEEKDAY_THURSDAY) \
+ || ((__VALUE__) == LL_RTC_WEEKDAY_FRIDAY) \
+ || ((__VALUE__) == LL_RTC_WEEKDAY_SATURDAY) \
+ || ((__VALUE__) == LL_RTC_WEEKDAY_SUNDAY))
+
+#define IS_LL_RTC_DAY(__DAY__) (((__DAY__) >= 1U) && ((__DAY__) <= 31U))
+
+#define IS_LL_RTC_MONTH(__VALUE__) (((__VALUE__) == LL_RTC_MONTH_JANUARY) \
+ || ((__VALUE__) == LL_RTC_MONTH_FEBRUARY) \
+ || ((__VALUE__) == LL_RTC_MONTH_MARCH) \
+ || ((__VALUE__) == LL_RTC_MONTH_APRIL) \
+ || ((__VALUE__) == LL_RTC_MONTH_MAY) \
+ || ((__VALUE__) == LL_RTC_MONTH_JUNE) \
+ || ((__VALUE__) == LL_RTC_MONTH_JULY) \
+ || ((__VALUE__) == LL_RTC_MONTH_AUGUST) \
+ || ((__VALUE__) == LL_RTC_MONTH_SEPTEMBER) \
+ || ((__VALUE__) == LL_RTC_MONTH_OCTOBER) \
+ || ((__VALUE__) == LL_RTC_MONTH_NOVEMBER) \
+ || ((__VALUE__) == LL_RTC_MONTH_DECEMBER))
+
+#define IS_LL_RTC_YEAR(__YEAR__) ((__YEAR__) <= 99U)
+
+#define IS_LL_RTC_ALMA_MASK(__VALUE__) (((__VALUE__) == LL_RTC_ALMA_MASK_NONE) \
+ || ((__VALUE__) == LL_RTC_ALMA_MASK_DATEWEEKDAY) \
+ || ((__VALUE__) == LL_RTC_ALMA_MASK_HOURS) \
+ || ((__VALUE__) == LL_RTC_ALMA_MASK_MINUTES) \
+ || ((__VALUE__) == LL_RTC_ALMA_MASK_SECONDS) \
+ || ((__VALUE__) == LL_RTC_ALMA_MASK_ALL))
+
+#define IS_LL_RTC_ALMB_MASK(__VALUE__) (((__VALUE__) == LL_RTC_ALMB_MASK_NONE) \
+ || ((__VALUE__) == LL_RTC_ALMB_MASK_DATEWEEKDAY) \
+ || ((__VALUE__) == LL_RTC_ALMB_MASK_HOURS) \
+ || ((__VALUE__) == LL_RTC_ALMB_MASK_MINUTES) \
+ || ((__VALUE__) == LL_RTC_ALMB_MASK_SECONDS) \
+ || ((__VALUE__) == LL_RTC_ALMB_MASK_ALL))
+
+
+#define IS_LL_RTC_ALMA_DATE_WEEKDAY_SEL(__SEL__) (((__SEL__) == LL_RTC_ALMA_DATEWEEKDAYSEL_DATE) || \
+ ((__SEL__) == LL_RTC_ALMA_DATEWEEKDAYSEL_WEEKDAY))
+
+#define IS_LL_RTC_ALMB_DATE_WEEKDAY_SEL(__SEL__) (((__SEL__) == LL_RTC_ALMB_DATEWEEKDAYSEL_DATE) || \
+ ((__SEL__) == LL_RTC_ALMB_DATEWEEKDAYSEL_WEEKDAY))
+
+
+/**
+ * @}
+ */
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup RTC_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup RTC_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-Initializes the RTC registers to their default reset values.
+ * @note This function does not reset the RTC Clock source and RTC Backup Data
+ * registers.
+ * @param RTCx RTC Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RTC registers are de-initialized
+ * - ERROR: RTC registers are not de-initialized
+ */
+ErrorStatus LL_RTC_DeInit(RTC_TypeDef *RTCx)
+{
+ ErrorStatus status = ERROR;
+
+ /* Check the parameter */
+ assert_param(IS_RTC_ALL_INSTANCE(RTCx));
+
+ /* Disable the write protection for RTC registers */
+ LL_RTC_DisableWriteProtection(RTCx);
+
+ /* Set Initialization mode */
+ if (LL_RTC_EnterInitMode(RTCx) != ERROR)
+ {
+ /* Reset TR, DR and CR registers */
+ LL_RTC_WriteReg(RTCx, TR, 0x00000000U);
+ LL_RTC_WriteReg(RTCx, DR, (RTC_DR_WDU_0 | RTC_DR_MU_0 | RTC_DR_DU_0));
+
+ /* Reset All CR bits except CR[2:0] */
+ LL_RTC_WriteReg(RTCx, CR, (LL_RTC_ReadReg(RTCx, CR) & RTC_CR_WUCKSEL));
+
+ LL_RTC_WriteReg(RTCx, WUTR, RTC_WUTR_WUT);
+ LL_RTC_WriteReg(RTCx, PRER, (RTC_PRER_PREDIV_A | RTC_SYNCH_PRESC_DEFAULT));
+ LL_RTC_WriteReg(RTCx, ALRMAR, 0x00000000U);
+ LL_RTC_WriteReg(RTCx, ALRMBR, 0x00000000U);
+ LL_RTC_WriteReg(RTCx, SHIFTR, 0x00000000U);
+ LL_RTC_WriteReg(RTCx, CALR, 0x00000000U);
+ LL_RTC_WriteReg(RTCx, ALRMASSR, 0x00000000U);
+ LL_RTC_WriteReg(RTCx, ALRMBSSR, 0x00000000U);
+
+#if defined(RTC_ICSR_ALRAWF)
+ /* Reset ICSR register and exit initialization mode */
+ LL_RTC_WriteReg(RTCx, ICSR, 0x00000000U);
+#endif /* RTC_ICSR_ALRAWF */
+#if defined(RTC_ISR_ALRAWF)
+ /* Reset ISR register and exit initialization mode */
+ LL_RTC_WriteReg(RTCx, ISR, 0x00000000U);
+#endif /* RTC_ISR_ALRAWF */
+
+#if defined(RTC_TAMPCR_TAMP1E)
+ /* Reset Tamper and alternate functions configuration register */
+ LL_RTC_WriteReg(RTCx, TAMPCR, 0x00000000U);
+#endif /* RTC_TAMPCR_TAMP1E */
+
+#if defined(RTC_OR_ALARMOUTTYPE)
+ /* Reset Option register */
+ LL_RTC_WriteReg(RTCx, OR, 0x00000000U);
+#endif /* RTC_OR_ALARMOUTTYPE */
+
+ /* Wait till the RTC RSF flag is set */
+ status = LL_RTC_WaitForSynchro(RTCx);
+ }
+
+ /* Enable the write protection for RTC registers */
+ LL_RTC_EnableWriteProtection(RTCx);
+
+#if defined (TAMP_CR1_TAMP1E)
+ /* DeInitialization of the TAMP */
+ LL_RTC_WriteReg(TAMP, CR1, 0xFFFF0000U);
+ LL_RTC_WriteReg(TAMP, FLTCR, 0x00000000U);
+ LL_RTC_WriteReg(TAMP, ATCR1, 0x00000000U);
+ LL_RTC_WriteReg(TAMP, IER, 0x00000000U);
+ LL_RTC_WriteReg(TAMP, SCR, 0xFFFFFFFFU);
+#endif /* TAMP_CR1_TAMP1E */
+
+ return status;
+}
+
+/**
+ * @brief Initializes the RTC registers according to the specified parameters
+ * in RTC_InitStruct.
+ * @param RTCx RTC Instance
+ * @param RTC_InitStruct pointer to a @ref LL_RTC_InitTypeDef structure that contains
+ * the configuration information for the RTC peripheral.
+ * @note The RTC Prescaler register is write protected and can be written in
+ * initialization mode only.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RTC registers are initialized
+ * - ERROR: RTC registers are not initialized
+ */
+ErrorStatus LL_RTC_Init(RTC_TypeDef *RTCx, LL_RTC_InitTypeDef *RTC_InitStruct)
+{
+ ErrorStatus status = ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(RTCx));
+ assert_param(IS_LL_RTC_HOURFORMAT(RTC_InitStruct->HourFormat));
+ assert_param(IS_LL_RTC_ASYNCH_PREDIV(RTC_InitStruct->AsynchPrescaler));
+ assert_param(IS_LL_RTC_SYNCH_PREDIV(RTC_InitStruct->SynchPrescaler));
+
+ /* Disable the write protection for RTC registers */
+ LL_RTC_DisableWriteProtection(RTCx);
+
+ /* Set Initialization mode */
+ if (LL_RTC_EnterInitMode(RTCx) != ERROR)
+ {
+ /* Set Hour Format */
+ LL_RTC_SetHourFormat(RTCx, RTC_InitStruct->HourFormat);
+
+ /* Configure Synchronous and Asynchronous prescaler factor */
+ LL_RTC_SetSynchPrescaler(RTCx, RTC_InitStruct->SynchPrescaler);
+ LL_RTC_SetAsynchPrescaler(RTCx, RTC_InitStruct->AsynchPrescaler);
+
+ /* Exit Initialization mode */
+ LL_RTC_DisableInitMode(RTCx);
+
+ status = SUCCESS;
+ }
+ /* Enable the write protection for RTC registers */
+ LL_RTC_EnableWriteProtection(RTCx);
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_RTC_InitTypeDef field to default value.
+ * @param RTC_InitStruct pointer to a @ref LL_RTC_InitTypeDef structure which will be initialized.
+ * @retval None
+ */
+void LL_RTC_StructInit(LL_RTC_InitTypeDef *RTC_InitStruct)
+{
+ /* Set RTC_InitStruct fields to default values */
+ RTC_InitStruct->HourFormat = LL_RTC_HOURFORMAT_24HOUR;
+ RTC_InitStruct->AsynchPrescaler = RTC_ASYNCH_PRESC_DEFAULT;
+ RTC_InitStruct->SynchPrescaler = RTC_SYNCH_PRESC_DEFAULT;
+}
+
+/**
+ * @brief Set the RTC current time.
+ * @param RTCx RTC Instance
+ * @param RTC_Format This parameter can be one of the following values:
+ * @arg @ref LL_RTC_FORMAT_BIN
+ * @arg @ref LL_RTC_FORMAT_BCD
+ * @param RTC_TimeStruct pointer to a RTC_TimeTypeDef structure that contains
+ * the time configuration information for the RTC.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RTC Time register is configured
+ * - ERROR: RTC Time register is not configured
+ */
+ErrorStatus LL_RTC_TIME_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_TimeTypeDef *RTC_TimeStruct)
+{
+ ErrorStatus status = ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(RTCx));
+ assert_param(IS_LL_RTC_FORMAT(RTC_Format));
+
+ if (RTC_Format == LL_RTC_FORMAT_BIN)
+ {
+ if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR)
+ {
+ assert_param(IS_LL_RTC_HOUR12(RTC_TimeStruct->Hours));
+ assert_param(IS_LL_RTC_TIME_FORMAT(RTC_TimeStruct->TimeFormat));
+ }
+ else
+ {
+ RTC_TimeStruct->TimeFormat = 0x00U;
+ assert_param(IS_LL_RTC_HOUR24(RTC_TimeStruct->Hours));
+ }
+ assert_param(IS_LL_RTC_MINUTES(RTC_TimeStruct->Minutes));
+ assert_param(IS_LL_RTC_SECONDS(RTC_TimeStruct->Seconds));
+ }
+ else
+ {
+ if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR)
+ {
+ assert_param(IS_LL_RTC_HOUR12(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Hours)));
+ assert_param(IS_LL_RTC_TIME_FORMAT(RTC_TimeStruct->TimeFormat));
+ }
+ else
+ {
+ RTC_TimeStruct->TimeFormat = 0x00U;
+ assert_param(IS_LL_RTC_HOUR24(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Hours)));
+ }
+ assert_param(IS_LL_RTC_MINUTES(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Minutes)));
+ assert_param(IS_LL_RTC_SECONDS(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Seconds)));
+ }
+
+ /* Disable the write protection for RTC registers */
+ LL_RTC_DisableWriteProtection(RTCx);
+
+ /* Set Initialization mode */
+ if (LL_RTC_EnterInitMode(RTCx) != ERROR)
+ {
+ /* Check the input parameters format */
+ if (RTC_Format != LL_RTC_FORMAT_BIN)
+ {
+ LL_RTC_TIME_Config(RTCx, RTC_TimeStruct->TimeFormat, RTC_TimeStruct->Hours,
+ RTC_TimeStruct->Minutes, RTC_TimeStruct->Seconds);
+ }
+ else
+ {
+ LL_RTC_TIME_Config(RTCx, RTC_TimeStruct->TimeFormat, __LL_RTC_CONVERT_BIN2BCD(RTC_TimeStruct->Hours),
+ __LL_RTC_CONVERT_BIN2BCD(RTC_TimeStruct->Minutes),
+ __LL_RTC_CONVERT_BIN2BCD(RTC_TimeStruct->Seconds));
+ }
+
+ /* Exit Initialization mode */
+ LL_RTC_DisableInitMode(RTC);
+
+ /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if (LL_RTC_IsShadowRegBypassEnabled(RTCx) == 0U)
+ {
+ status = LL_RTC_WaitForSynchro(RTCx);
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+ /* Enable the write protection for RTC registers */
+ LL_RTC_EnableWriteProtection(RTCx);
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_RTC_TimeTypeDef field to default value (Time = 00h:00min:00sec).
+ * @param RTC_TimeStruct pointer to a @ref LL_RTC_TimeTypeDef structure which will be initialized.
+ * @retval None
+ */
+void LL_RTC_TIME_StructInit(LL_RTC_TimeTypeDef *RTC_TimeStruct)
+{
+ /* Time = 00h:00min:00sec */
+ RTC_TimeStruct->TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24;
+ RTC_TimeStruct->Hours = 0U;
+ RTC_TimeStruct->Minutes = 0U;
+ RTC_TimeStruct->Seconds = 0U;
+}
+
+/**
+ * @brief Set the RTC current date.
+ * @param RTCx RTC Instance
+ * @param RTC_Format This parameter can be one of the following values:
+ * @arg @ref LL_RTC_FORMAT_BIN
+ * @arg @ref LL_RTC_FORMAT_BCD
+ * @param RTC_DateStruct: pointer to a RTC_DateTypeDef structure that contains
+ * the date configuration information for the RTC.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RTC Day register is configured
+ * - ERROR: RTC Day register is not configured
+ */
+ErrorStatus LL_RTC_DATE_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_DateTypeDef *RTC_DateStruct)
+{
+ ErrorStatus status = ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(RTCx));
+ assert_param(IS_LL_RTC_FORMAT(RTC_Format));
+
+ if ((RTC_Format == LL_RTC_FORMAT_BIN) && ((RTC_DateStruct->Month & 0x10U) == 0x10U))
+ {
+ RTC_DateStruct->Month = (uint8_t)((RTC_DateStruct->Month & (uint8_t)~(0x10U)) + 0x0AU);
+ }
+ if (RTC_Format == LL_RTC_FORMAT_BIN)
+ {
+ assert_param(IS_LL_RTC_YEAR(RTC_DateStruct->Year));
+ assert_param(IS_LL_RTC_MONTH(RTC_DateStruct->Month));
+ assert_param(IS_LL_RTC_DAY(RTC_DateStruct->Day));
+ }
+ else
+ {
+ assert_param(IS_LL_RTC_YEAR(__LL_RTC_CONVERT_BCD2BIN(RTC_DateStruct->Year)));
+ assert_param(IS_LL_RTC_MONTH(__LL_RTC_CONVERT_BCD2BIN(RTC_DateStruct->Month)));
+ assert_param(IS_LL_RTC_DAY(__LL_RTC_CONVERT_BCD2BIN(RTC_DateStruct->Day)));
+ }
+ assert_param(IS_LL_RTC_WEEKDAY(RTC_DateStruct->WeekDay));
+
+ /* Disable the write protection for RTC registers */
+ LL_RTC_DisableWriteProtection(RTCx);
+
+ /* Set Initialization mode */
+ if (LL_RTC_EnterInitMode(RTCx) != ERROR)
+ {
+ /* Check the input parameters format */
+ if (RTC_Format != LL_RTC_FORMAT_BIN)
+ {
+ LL_RTC_DATE_Config(RTCx, RTC_DateStruct->WeekDay, RTC_DateStruct->Day, RTC_DateStruct->Month, RTC_DateStruct->Year);
+ }
+ else
+ {
+ LL_RTC_DATE_Config(RTCx, RTC_DateStruct->WeekDay, __LL_RTC_CONVERT_BIN2BCD(RTC_DateStruct->Day),
+ __LL_RTC_CONVERT_BIN2BCD(RTC_DateStruct->Month), __LL_RTC_CONVERT_BIN2BCD(RTC_DateStruct->Year));
+ }
+
+ /* Exit Initialization mode */
+ LL_RTC_DisableInitMode(RTC);
+
+ /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if (LL_RTC_IsShadowRegBypassEnabled(RTCx) == 0U)
+ {
+ status = LL_RTC_WaitForSynchro(RTCx);
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+ /* Enable the write protection for RTC registers */
+ LL_RTC_EnableWriteProtection(RTCx);
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_RTC_DateTypeDef field to default value (date = Monday, January 01 xx00)
+ * @param RTC_DateStruct pointer to a @ref LL_RTC_DateTypeDef structure which will be initialized.
+ * @retval None
+ */
+void LL_RTC_DATE_StructInit(LL_RTC_DateTypeDef *RTC_DateStruct)
+{
+ /* Monday, January 01 xx00 */
+ RTC_DateStruct->WeekDay = LL_RTC_WEEKDAY_MONDAY;
+ RTC_DateStruct->Day = 1U;
+ RTC_DateStruct->Month = LL_RTC_MONTH_JANUARY;
+ RTC_DateStruct->Year = 0U;
+}
+
+/**
+ * @brief Set the RTC Alarm A.
+ * @note The Alarm register can only be written when the corresponding Alarm
+ * is disabled (Use @ref LL_RTC_ALMA_Disable function).
+ * @param RTCx RTC Instance
+ * @param RTC_Format This parameter can be one of the following values:
+ * @arg @ref LL_RTC_FORMAT_BIN
+ * @arg @ref LL_RTC_FORMAT_BCD
+ * @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure that
+ * contains the alarm configuration parameters.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: ALARMA registers are configured
+ * - ERROR: ALARMA registers are not configured
+ */
+ErrorStatus LL_RTC_ALMA_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_AlarmTypeDef *RTC_AlarmStruct)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(RTCx));
+ assert_param(IS_LL_RTC_FORMAT(RTC_Format));
+ assert_param(IS_LL_RTC_ALMA_MASK(RTC_AlarmStruct->AlarmMask));
+ assert_param(IS_LL_RTC_ALMA_DATE_WEEKDAY_SEL(RTC_AlarmStruct->AlarmDateWeekDaySel));
+
+ if (RTC_Format == LL_RTC_FORMAT_BIN)
+ {
+ if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR)
+ {
+ assert_param(IS_LL_RTC_HOUR12(RTC_AlarmStruct->AlarmTime.Hours));
+ assert_param(IS_LL_RTC_TIME_FORMAT(RTC_AlarmStruct->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ RTC_AlarmStruct->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_LL_RTC_HOUR24(RTC_AlarmStruct->AlarmTime.Hours));
+ }
+ assert_param(IS_LL_RTC_MINUTES(RTC_AlarmStruct->AlarmTime.Minutes));
+ assert_param(IS_LL_RTC_SECONDS(RTC_AlarmStruct->AlarmTime.Seconds));
+
+ if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMA_DATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_LL_RTC_DAY(RTC_AlarmStruct->AlarmDateWeekDay));
+ }
+ else
+ {
+ assert_param(IS_LL_RTC_WEEKDAY(RTC_AlarmStruct->AlarmDateWeekDay));
+ }
+ }
+ else
+ {
+ if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR)
+ {
+ assert_param(IS_LL_RTC_HOUR12(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours)));
+ assert_param(IS_LL_RTC_TIME_FORMAT(RTC_AlarmStruct->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ RTC_AlarmStruct->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_LL_RTC_HOUR24(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours)));
+ }
+
+ assert_param(IS_LL_RTC_MINUTES(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Minutes)));
+ assert_param(IS_LL_RTC_SECONDS(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Seconds)));
+
+ if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMA_DATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_LL_RTC_DAY(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmDateWeekDay)));
+ }
+ else
+ {
+ assert_param(IS_LL_RTC_WEEKDAY(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmDateWeekDay)));
+ }
+ }
+
+ /* Disable the write protection for RTC registers */
+ LL_RTC_DisableWriteProtection(RTCx);
+
+ /* Select weekday selection */
+ if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMA_DATEWEEKDAYSEL_DATE)
+ {
+ /* Set the date for ALARM */
+ LL_RTC_ALMA_DisableWeekday(RTCx);
+ if (RTC_Format != LL_RTC_FORMAT_BIN)
+ {
+ LL_RTC_ALMA_SetDay(RTCx, RTC_AlarmStruct->AlarmDateWeekDay);
+ }
+ else
+ {
+ LL_RTC_ALMA_SetDay(RTCx, __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmDateWeekDay));
+ }
+ }
+ else
+ {
+ /* Set the week day for ALARM */
+ LL_RTC_ALMA_EnableWeekday(RTCx);
+ LL_RTC_ALMA_SetWeekDay(RTCx, RTC_AlarmStruct->AlarmDateWeekDay);
+ }
+
+ /* Configure the Alarm register */
+ if (RTC_Format != LL_RTC_FORMAT_BIN)
+ {
+ LL_RTC_ALMA_ConfigTime(RTCx, RTC_AlarmStruct->AlarmTime.TimeFormat, RTC_AlarmStruct->AlarmTime.Hours,
+ RTC_AlarmStruct->AlarmTime.Minutes, RTC_AlarmStruct->AlarmTime.Seconds);
+ }
+ else
+ {
+ LL_RTC_ALMA_ConfigTime(RTCx, RTC_AlarmStruct->AlarmTime.TimeFormat,
+ __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Hours),
+ __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Minutes),
+ __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Seconds));
+ }
+ /* Set ALARM mask */
+ LL_RTC_ALMA_SetMask(RTCx, RTC_AlarmStruct->AlarmMask);
+
+ /* Enable the write protection for RTC registers */
+ LL_RTC_EnableWriteProtection(RTCx);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Set the RTC Alarm B.
+ * @note The Alarm register can only be written when the corresponding Alarm
+ * is disabled (@ref LL_RTC_ALMB_Disable function).
+ * @param RTCx RTC Instance
+ * @param RTC_Format This parameter can be one of the following values:
+ * @arg @ref LL_RTC_FORMAT_BIN
+ * @arg @ref LL_RTC_FORMAT_BCD
+ * @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure that
+ * contains the alarm configuration parameters.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: ALARMB registers are configured
+ * - ERROR: ALARMB registers are not configured
+ */
+ErrorStatus LL_RTC_ALMB_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_AlarmTypeDef *RTC_AlarmStruct)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(RTCx));
+ assert_param(IS_LL_RTC_FORMAT(RTC_Format));
+ assert_param(IS_LL_RTC_ALMB_MASK(RTC_AlarmStruct->AlarmMask));
+ assert_param(IS_LL_RTC_ALMB_DATE_WEEKDAY_SEL(RTC_AlarmStruct->AlarmDateWeekDaySel));
+
+ if (RTC_Format == LL_RTC_FORMAT_BIN)
+ {
+ if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR)
+ {
+ assert_param(IS_LL_RTC_HOUR12(RTC_AlarmStruct->AlarmTime.Hours));
+ assert_param(IS_LL_RTC_TIME_FORMAT(RTC_AlarmStruct->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ RTC_AlarmStruct->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_LL_RTC_HOUR24(RTC_AlarmStruct->AlarmTime.Hours));
+ }
+ assert_param(IS_LL_RTC_MINUTES(RTC_AlarmStruct->AlarmTime.Minutes));
+ assert_param(IS_LL_RTC_SECONDS(RTC_AlarmStruct->AlarmTime.Seconds));
+
+ if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMB_DATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_LL_RTC_DAY(RTC_AlarmStruct->AlarmDateWeekDay));
+ }
+ else
+ {
+ assert_param(IS_LL_RTC_WEEKDAY(RTC_AlarmStruct->AlarmDateWeekDay));
+ }
+ }
+ else
+ {
+ if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR)
+ {
+ assert_param(IS_LL_RTC_HOUR12(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours)));
+ assert_param(IS_LL_RTC_TIME_FORMAT(RTC_AlarmStruct->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ RTC_AlarmStruct->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_LL_RTC_HOUR24(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours)));
+ }
+
+ assert_param(IS_LL_RTC_MINUTES(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Minutes)));
+ assert_param(IS_LL_RTC_SECONDS(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Seconds)));
+
+ if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMB_DATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_LL_RTC_DAY(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmDateWeekDay)));
+ }
+ else
+ {
+ assert_param(IS_LL_RTC_WEEKDAY(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmDateWeekDay)));
+ }
+ }
+
+ /* Disable the write protection for RTC registers */
+ LL_RTC_DisableWriteProtection(RTCx);
+
+ /* Select weekday selection */
+ if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMB_DATEWEEKDAYSEL_DATE)
+ {
+ /* Set the date for ALARM */
+ LL_RTC_ALMB_DisableWeekday(RTCx);
+ if (RTC_Format != LL_RTC_FORMAT_BIN)
+ {
+ LL_RTC_ALMB_SetDay(RTCx, RTC_AlarmStruct->AlarmDateWeekDay);
+ }
+ else
+ {
+ LL_RTC_ALMB_SetDay(RTCx, __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmDateWeekDay));
+ }
+ }
+ else
+ {
+ /* Set the week day for ALARM */
+ LL_RTC_ALMB_EnableWeekday(RTCx);
+ LL_RTC_ALMB_SetWeekDay(RTCx, RTC_AlarmStruct->AlarmDateWeekDay);
+ }
+
+ /* Configure the Alarm register */
+ if (RTC_Format != LL_RTC_FORMAT_BIN)
+ {
+ LL_RTC_ALMB_ConfigTime(RTCx, RTC_AlarmStruct->AlarmTime.TimeFormat, RTC_AlarmStruct->AlarmTime.Hours,
+ RTC_AlarmStruct->AlarmTime.Minutes, RTC_AlarmStruct->AlarmTime.Seconds);
+ }
+ else
+ {
+ LL_RTC_ALMB_ConfigTime(RTCx, RTC_AlarmStruct->AlarmTime.TimeFormat,
+ __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Hours),
+ __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Minutes),
+ __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Seconds));
+ }
+ /* Set ALARM mask */
+ LL_RTC_ALMB_SetMask(RTCx, RTC_AlarmStruct->AlarmMask);
+
+ /* Enable the write protection for RTC registers */
+ LL_RTC_EnableWriteProtection(RTCx);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Set each @ref LL_RTC_AlarmTypeDef of ALARMA field to default value (Time = 00h:00mn:00sec /
+ * Day = 1st day of the month/Mask = all fields are masked).
+ * @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure which will be initialized.
+ * @retval None
+ */
+void LL_RTC_ALMA_StructInit(LL_RTC_AlarmTypeDef *RTC_AlarmStruct)
+{
+ /* Alarm Time Settings : Time = 00h:00mn:00sec */
+ RTC_AlarmStruct->AlarmTime.TimeFormat = LL_RTC_ALMA_TIME_FORMAT_AM;
+ RTC_AlarmStruct->AlarmTime.Hours = 0U;
+ RTC_AlarmStruct->AlarmTime.Minutes = 0U;
+ RTC_AlarmStruct->AlarmTime.Seconds = 0U;
+
+ /* Alarm Day Settings : Day = 1st day of the month */
+ RTC_AlarmStruct->AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE;
+ RTC_AlarmStruct->AlarmDateWeekDay = 1U;
+
+ /* Alarm Masks Settings : Mask = all fields are not masked */
+ RTC_AlarmStruct->AlarmMask = LL_RTC_ALMA_MASK_NONE;
+}
+
+/**
+ * @brief Set each @ref LL_RTC_AlarmTypeDef of ALARMA field to default value (Time = 00h:00mn:00sec /
+ * Day = 1st day of the month/Mask = all fields are masked).
+ * @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure which will be initialized.
+ * @retval None
+ */
+void LL_RTC_ALMB_StructInit(LL_RTC_AlarmTypeDef *RTC_AlarmStruct)
+{
+ /* Alarm Time Settings : Time = 00h:00mn:00sec */
+ RTC_AlarmStruct->AlarmTime.TimeFormat = LL_RTC_ALMB_TIME_FORMAT_AM;
+ RTC_AlarmStruct->AlarmTime.Hours = 0U;
+ RTC_AlarmStruct->AlarmTime.Minutes = 0U;
+ RTC_AlarmStruct->AlarmTime.Seconds = 0U;
+
+ /* Alarm Day Settings : Day = 1st day of the month */
+ RTC_AlarmStruct->AlarmDateWeekDaySel = LL_RTC_ALMB_DATEWEEKDAYSEL_DATE;
+ RTC_AlarmStruct->AlarmDateWeekDay = 1U;
+
+ /* Alarm Masks Settings : Mask = all fields are not masked */
+ RTC_AlarmStruct->AlarmMask = LL_RTC_ALMB_MASK_NONE;
+}
+
+/**
+ * @brief Enters the RTC Initialization mode.
+ * @note The RTC Initialization mode is write protected, use the
+ * @ref LL_RTC_DisableWriteProtection before calling this function.
+ * @param RTCx RTC Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RTC is in Init mode
+ * - ERROR: RTC is not in Init mode
+ */
+ErrorStatus LL_RTC_EnterInitMode(RTC_TypeDef *RTCx)
+{
+ __IO uint32_t timeout = RTC_INITMODE_TIMEOUT;
+ ErrorStatus status = SUCCESS;
+ uint32_t tmp;
+
+ /* Check the parameter */
+ assert_param(IS_RTC_ALL_INSTANCE(RTCx));
+
+ /* Check if the Initialization mode is set */
+ if (LL_RTC_IsActiveFlag_INIT(RTCx) == 0U)
+ {
+ /* Set the Initialization mode */
+ LL_RTC_EnableInitMode(RTCx);
+
+ /* Wait till RTC is in INIT state and if Time out is reached exit */
+ tmp = LL_RTC_IsActiveFlag_INIT(RTCx);
+ while ((timeout != 0U) && (tmp != 1U))
+ {
+ if (LL_SYSTICK_IsActiveCounterFlag() == 1U)
+ {
+ timeout --;
+ }
+ tmp = LL_RTC_IsActiveFlag_INIT(RTCx);
+ if (timeout == 0U)
+ {
+ status = ERROR;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Exit the RTC Initialization mode.
+ * @note When the initialization sequence is complete, the calendar restarts
+ * counting after 4 RTCCLK cycles.
+ * @note The RTC Initialization mode is write protected, use the
+ * @ref LL_RTC_DisableWriteProtection before calling this function.
+ * @param RTCx RTC Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RTC exited from in Init mode
+ * - ERROR: Not applicable
+ */
+ErrorStatus LL_RTC_ExitInitMode(RTC_TypeDef *RTCx)
+{
+ /* Check the parameter */
+ assert_param(IS_RTC_ALL_INSTANCE(RTCx));
+
+ /* Disable initialization mode */
+ LL_RTC_DisableInitMode(RTCx);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Waits until the RTC Time and Day registers (RTC_TR and RTC_DR) are
+ * synchronized with RTC APB clock.
+ * @note The RTC Resynchronization mode is write protected, use the
+ * @ref LL_RTC_DisableWriteProtection before calling this function.
+ * @note To read the calendar through the shadow registers after Calendar
+ * initialization, calendar update or after wakeup from low power modes
+ * the software must first clear the RSF flag.
+ * The software must then wait until it is set again before reading
+ * the calendar, which means that the calendar registers have been
+ * correctly copied into the RTC_TR and RTC_DR shadow registers.
+ * @param RTCx RTC Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RTC registers are synchronised
+ * - ERROR: RTC registers are not synchronised
+ */
+ErrorStatus LL_RTC_WaitForSynchro(RTC_TypeDef *RTCx)
+{
+ __IO uint32_t timeout = RTC_SYNCHRO_TIMEOUT;
+ ErrorStatus status = SUCCESS;
+ uint32_t tmp;
+
+ /* Check the parameter */
+ assert_param(IS_RTC_ALL_INSTANCE(RTCx));
+
+ /* Clear RSF flag */
+ LL_RTC_ClearFlag_RS(RTCx);
+
+ /* Wait the registers to be synchronised */
+ tmp = LL_RTC_IsActiveFlag_RS(RTCx);
+ while ((timeout != 0U) && (tmp != 0U))
+ {
+ if (LL_SYSTICK_IsActiveCounterFlag() == 1U)
+ {
+ timeout--;
+ }
+ tmp = LL_RTC_IsActiveFlag_RS(RTCx);
+ if (timeout == 0U)
+ {
+ status = ERROR;
+ }
+ }
+
+ if (status != ERROR)
+ {
+ timeout = RTC_SYNCHRO_TIMEOUT;
+ tmp = LL_RTC_IsActiveFlag_RS(RTCx);
+ while ((timeout != 0U) && (tmp != 1U))
+ {
+ if (LL_SYSTICK_IsActiveCounterFlag() == 1U)
+ {
+ timeout--;
+ }
+ tmp = LL_RTC_IsActiveFlag_RS(RTCx);
+ if (timeout == 0U)
+ {
+ status = ERROR;
+ }
+ }
+ }
+
+ return (status);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined(RTC) */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_sdmmc.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_sdmmc.c
new file mode 100644
index 0000000000..e97363a1b4
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_sdmmc.c
@@ -0,0 +1,1582 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_sdmmc.c
+ * @author MCD Application Team
+ * @brief SDMMC Low Layer HAL module driver.
+ *
+ * This file provides firmware functions to manage the following
+ * functionalities of the SDMMC peripheral:
+ * + Initialization/de-initialization functions
+ * + I/O operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### SDMMC peripheral features #####
+ ==============================================================================
+ [..] The SD/SDMMC MMC card host interface (SDMMC) provides an interface between the AHB
+ peripheral bus and MultiMedia cards (MMCs), SD memory cards, SDMMC cards and CE-ATA
+ devices.
+
+ [..] The SDMMC features include the following:
+ (+) Full compliance with MultiMediaCard System Specification Version 4.51. Card support
+ for three different databus modes: 1-bit (default), 4-bit and 8-bit.
+ (+) Full compatibility with previous versions of MultiMediaCards (backward compatibility).
+ (+) Full compliance with SD memory card specifications version 4.1.
+ (SDR104 SDMMC_CK speed limited to maximum allowed IO speed, SPI mode and
+ UHS-II mode not supported).
+ (+) Full compliance with SDIO card specification version 4.0. Card support
+ for two different databus modes: 1-bit (default) and 4-bit.
+ (SDR104 SDMMC_CK speed limited to maximum allowed IO speed, SPI mode and
+ UHS-II mode not supported).
+ (+) Data transfer up to 208 Mbyte/s for the 8 bit mode. (depending maximum allowed IO speed).
+ (+) Data and command output enable signals to control external bidirectional drivers
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver is a considered as a driver of service for external devices drivers
+ that interfaces with the SDMMC peripheral.
+ According to the device used (SD card/ MMC card / SDMMC card ...), a set of APIs
+ is used in the device's driver to perform SDMMC operations and functionalities.
+
+ This driver is almost transparent for the final user, it is only used to implement other
+ functionalities of the external device.
+
+ [..]
+ (+) The SDMMC clock is coming from output of PLL1_Q or PLL2_R.
+ Before start working with SDMMC peripheral make sure that the PLL is well configured.
+ The SDMMC peripheral uses two clock signals:
+ (++) PLL1_Q bus clock (default after reset)
+ (++) PLL2_R bus clock
+
+ (+) Enable/Disable peripheral clock using RCC peripheral macros related to SDMMC
+ peripheral.
+
+ (+) Enable the Power ON State using the SDMMC_PowerState_ON(SDMMCx)
+ function and disable it using the function SDMMC_PowerState_OFF(SDMMCx).
+
+ (+) Enable/Disable the peripheral interrupts using the macros __SDMMC_ENABLE_IT(hSDMMC, IT)
+ and __SDMMC_DISABLE_IT(hSDMMC, IT) if you need to use interrupt mode.
+
+ (+) When using the DMA mode
+ (++) Configure the IDMA mode (Single buffer or double)
+ (++) Configure the buffer address
+ (++) Configure Data Path State Machine
+
+ (+) To control the CPSM (Command Path State Machine) and send
+ commands to the card use the SDMMC_SendCommand(SDMMCx),
+ SDMMC_GetCommandResponse() and SDMMC_GetResponse() functions. First, user has
+ to fill the command structure (pointer to SDMMC_CmdInitTypeDef) according
+ to the selected command to be sent.
+ The parameters that should be filled are:
+ (++) Command Argument
+ (++) Command Index
+ (++) Command Response type
+ (++) Command Wait
+ (++) CPSM Status (Enable or Disable).
+
+ -@@- To check if the command is well received, read the SDMMC_CMDRESP
+ register using the SDMMC_GetCommandResponse().
+ The SDMMC responses registers (SDMMC_RESP1 to SDMMC_RESP2), use the
+ SDMMC_GetResponse() function.
+
+ (+) To control the DPSM (Data Path State Machine) and send/receive
+ data to/from the card use the SDMMC_DataConfig(), SDMMC_GetDataCounter(),
+ SDMMC_ReadFIFO(), SDMMC_WriteFIFO() and SDMMC_GetFIFOCount() functions.
+
+ *** Read Operations ***
+ =======================
+ [..]
+ (#) First, user has to fill the data structure (pointer to
+ SDMMC_DataInitTypeDef) according to the selected data type to be received.
+ The parameters that should be filled are:
+ (++) Data TimeOut
+ (++) Data Length
+ (++) Data Block size
+ (++) Data Transfer direction: should be from card (To SDMMC)
+ (++) Data Transfer mode
+ (++) DPSM Status (Enable or Disable)
+
+ (#) Configure the SDMMC resources to receive the data from the card
+ according to selected transfer mode (Refer to Step 8, 9 and 10).
+
+ (#) Send the selected Read command (refer to step 11).
+
+ (#) Use the SDMMC flags/interrupts to check the transfer status.
+
+ *** Write Operations ***
+ ========================
+ [..]
+ (#) First, user has to fill the data structure (pointer to
+ SDMMC_DataInitTypeDef) according to the selected data type to be received.
+ The parameters that should be filled are:
+ (++) Data TimeOut
+ (++) Data Length
+ (++) Data Block size
+ (++) Data Transfer direction: should be to card (To CARD)
+ (++) Data Transfer mode
+ (++) DPSM Status (Enable or Disable)
+
+ (#) Configure the SDMMC resources to send the data to the card according to
+ selected transfer mode.
+
+ (#) Send the selected Write command.
+
+ (#) Use the SDMMC flags/interrupts to check the transfer status.
+
+ *** Command management operations ***
+ =====================================
+ [..]
+ (#) The commands used for Read/Write/Erase operations are managed in
+ separate functions.
+ Each function allows to send the needed command with the related argument,
+ then check the response.
+ By the same approach, you could implement a command and check the response.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SDMMC_LL SDMMC Low Layer
+ * @brief Low layer module for SD
+ * @{
+ */
+
+#if defined (HAL_SD_MODULE_ENABLED) || defined (HAL_MMC_MODULE_ENABLED)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static uint32_t SDMMC_GetCmdError(SDMMC_TypeDef *SDMMCx);
+static uint32_t SDMMC_GetCmdResp1(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint32_t Timeout);
+static uint32_t SDMMC_GetCmdResp2(SDMMC_TypeDef *SDMMCx);
+static uint32_t SDMMC_GetCmdResp3(SDMMC_TypeDef *SDMMCx);
+static uint32_t SDMMC_GetCmdResp7(SDMMC_TypeDef *SDMMCx);
+static uint32_t SDMMC_GetCmdResp6(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint16_t *pRCA);
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup SDMMC_LL_Exported_Functions SDMMC Low Layer Exported Functions
+ * @{
+ */
+
+/** @defgroup HAL_SDMMC_LL_Group1 Initialization de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization/de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the SDMMC according to the specified
+ * parameters in the SDMMC_InitTypeDef and create the associated handle.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Init: SDMMC initialization structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_Init(SDMMC_TypeDef *SDMMCx, SDMMC_InitTypeDef Init)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_ALL_INSTANCE(SDMMCx));
+ assert_param(IS_SDMMC_CLOCK_EDGE(Init.ClockEdge));
+ assert_param(IS_SDMMC_CLOCK_POWER_SAVE(Init.ClockPowerSave));
+ assert_param(IS_SDMMC_BUS_WIDE(Init.BusWide));
+ assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(Init.HardwareFlowControl));
+ assert_param(IS_SDMMC_CLKDIV(Init.ClockDiv));
+
+ /* Set SDMMC configuration parameters */
+ tmpreg |= (Init.ClockEdge |\
+ Init.ClockPowerSave |\
+ Init.BusWide |\
+ Init.HardwareFlowControl |\
+ Init.ClockDiv
+ );
+
+ /* Write to SDMMC CLKCR */
+ MODIFY_REG(SDMMCx->CLKCR, CLKCR_CLEAR_MASK, tmpreg);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_SDMMC_LL_Group2 IO operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ ##### I/O operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the SDMMC data
+ transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Read data (word) from Rx FIFO in blocking mode (polling)
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_ReadFIFO(SDMMC_TypeDef *SDMMCx)
+{
+ /* Read data from Rx FIFO */
+ return (SDMMCx->FIFO);
+}
+
+/**
+ * @brief Write data (word) to Tx FIFO in blocking mode (polling)
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param pWriteData: pointer to data to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_WriteFIFO(SDMMC_TypeDef *SDMMCx, uint32_t *pWriteData)
+{
+ /* Write data to FIFO */
+ SDMMCx->FIFO = *pWriteData;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_SDMMC_LL_Group3 Peripheral Control functions
+ * @brief management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the SDMMC data
+ transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set SDMMC Power state to ON.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_PowerState_ON(SDMMC_TypeDef *SDMMCx)
+{
+ /* Set power state to ON */
+ SDMMCx->POWER |= SDMMC_POWER_PWRCTRL;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set SDMMC Power state to Power-Cycle.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_PowerState_Cycle(SDMMC_TypeDef *SDMMCx)
+{
+ /* Set power state to Power Cycle*/
+ SDMMCx->POWER |= SDMMC_POWER_PWRCTRL_1;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set SDMMC Power state to OFF.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_PowerState_OFF(SDMMC_TypeDef *SDMMCx)
+{
+ /* Set power state to OFF */
+ SDMMCx->POWER &= ~(SDMMC_POWER_PWRCTRL);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get SDMMC Power state.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval Power status of the controller. The returned value can be one of the
+ * following values:
+ * - 0x00: Power OFF
+ * - 0x02: Power UP
+ * - 0x03: Power ON
+ */
+uint32_t SDMMC_GetPowerState(SDMMC_TypeDef *SDMMCx)
+{
+ return (SDMMCx->POWER & SDMMC_POWER_PWRCTRL);
+}
+
+/**
+ * @brief Configure the SDMMC command path according to the specified parameters in
+ * SDMMC_CmdInitTypeDef structure and send the command
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Command: pointer to a SDMMC_CmdInitTypeDef structure that contains
+ * the configuration information for the SDMMC command
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_SendCommand(SDMMC_TypeDef *SDMMCx, SDMMC_CmdInitTypeDef *Command)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_CMD_INDEX(Command->CmdIndex));
+ assert_param(IS_SDMMC_RESPONSE(Command->Response));
+ assert_param(IS_SDMMC_WAIT(Command->WaitForInterrupt));
+ assert_param(IS_SDMMC_CPSM(Command->CPSM));
+
+ /* Set the SDMMC Argument value */
+ SDMMCx->ARG = Command->Argument;
+
+ /* Set SDMMC command parameters */
+ tmpreg |= (uint32_t)(Command->CmdIndex |\
+ Command->Response |\
+ Command->WaitForInterrupt |\
+ Command->CPSM);
+
+ /* Write to SDMMC CMD register */
+ MODIFY_REG(SDMMCx->CMD, CMD_CLEAR_MASK, tmpreg);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Return the command index of last command for which response received
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval Command index of the last command response received
+ */
+uint8_t SDMMC_GetCommandResponse(SDMMC_TypeDef *SDMMCx)
+{
+ return (uint8_t)(SDMMCx->RESPCMD);
+}
+
+
+/**
+ * @brief Return the response received from the card for the last command
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Response: Specifies the SDMMC response register.
+ * This parameter can be one of the following values:
+ * @arg SDMMC_RESP1: Response Register 1
+ * @arg SDMMC_RESP2: Response Register 2
+ * @arg SDMMC_RESP3: Response Register 3
+ * @arg SDMMC_RESP4: Response Register 4
+ * @retval The Corresponding response register value
+ */
+uint32_t SDMMC_GetResponse(SDMMC_TypeDef *SDMMCx, uint32_t Response)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_RESP(Response));
+
+ /* Get the response */
+ tmp = (uint32_t)(&(SDMMCx->RESP1)) + Response;
+
+ return (*(__IO uint32_t *) tmp);
+}
+
+/**
+ * @brief Configure the SDMMC data path according to the specified
+ * parameters in the SDMMC_DataInitTypeDef.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Data : pointer to a SDMMC_DataInitTypeDef structure
+ * that contains the configuration information for the SDMMC data.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_ConfigData(SDMMC_TypeDef *SDMMCx, SDMMC_DataInitTypeDef* Data)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_DATA_LENGTH(Data->DataLength));
+ assert_param(IS_SDMMC_BLOCK_SIZE(Data->DataBlockSize));
+ assert_param(IS_SDMMC_TRANSFER_DIR(Data->TransferDir));
+ assert_param(IS_SDMMC_TRANSFER_MODE(Data->TransferMode));
+ assert_param(IS_SDMMC_DPSM(Data->DPSM));
+
+ /* Set the SDMMC Data TimeOut value */
+ SDMMCx->DTIMER = Data->DataTimeOut;
+
+ /* Set the SDMMC DataLength value */
+ SDMMCx->DLEN = Data->DataLength;
+
+ /* Set the SDMMC data configuration parameters */
+ tmpreg |= (uint32_t)(Data->DataBlockSize |\
+ Data->TransferDir |\
+ Data->TransferMode |\
+ Data->DPSM);
+
+ /* Write to SDMMC DCTRL */
+ MODIFY_REG(SDMMCx->DCTRL, DCTRL_CLEAR_MASK, tmpreg);
+
+ return HAL_OK;
+
+}
+
+/**
+ * @brief Returns number of remaining data bytes to be transferred.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval Number of remaining data bytes to be transferred
+ */
+uint32_t SDMMC_GetDataCounter(SDMMC_TypeDef *SDMMCx)
+{
+ return (SDMMCx->DCOUNT);
+}
+
+/**
+ * @brief Get the FIFO data
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval Data received
+ */
+uint32_t SDMMC_GetFIFOCount(SDMMC_TypeDef *SDMMCx)
+{
+ return (SDMMCx->FIFO);
+}
+
+/**
+ * @brief Sets one of the two options of inserting read wait interval.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param SDMMC_ReadWaitMode: SDMMC Read Wait operation mode.
+ * This parameter can be:
+ * @arg SDMMC_READ_WAIT_MODE_CLK: Read Wait control by stopping SDMMCCLK
+ * @arg SDMMC_READ_WAIT_MODE_DATA2: Read Wait control using SDMMC_DATA2
+ * @retval None
+ */
+HAL_StatusTypeDef SDMMC_SetSDMMCReadWaitMode(SDMMC_TypeDef *SDMMCx, uint32_t SDMMC_ReadWaitMode)
+{
+ /* Check the parameters */
+ assert_param(IS_SDMMC_READWAIT_MODE(SDMMC_ReadWaitMode));
+
+ /* Set SDMMC read wait mode */
+ MODIFY_REG(SDMMCx->DCTRL, SDMMC_DCTRL_RWMOD, SDMMC_ReadWaitMode);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+
+/** @defgroup HAL_SDMMC_LL_Group4 Command management functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Commands management functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the needed commands.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Send the Data Block Lenght command and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdBlockLength(SDMMC_TypeDef *SDMMCx, uint32_t BlockSize)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = (uint32_t)BlockSize;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_BLOCKLEN;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SET_BLOCKLEN, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Read Single Block command and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdReadSingleBlock(SDMMC_TypeDef *SDMMCx, uint32_t ReadAdd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = (uint32_t)ReadAdd;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_SINGLE_BLOCK;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_READ_SINGLE_BLOCK, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Read Multi Block command and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdReadMultiBlock(SDMMC_TypeDef *SDMMCx, uint32_t ReadAdd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = (uint32_t)ReadAdd;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_MULT_BLOCK;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_READ_MULT_BLOCK, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Write Single Block command and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdWriteSingleBlock(SDMMC_TypeDef *SDMMCx, uint32_t WriteAdd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = (uint32_t)WriteAdd;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_WRITE_SINGLE_BLOCK;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_WRITE_SINGLE_BLOCK, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Write Multi Block command and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdWriteMultiBlock(SDMMC_TypeDef *SDMMCx, uint32_t WriteAdd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = (uint32_t)WriteAdd;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_WRITE_MULT_BLOCK;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_WRITE_MULT_BLOCK, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Start Address Erase command for SD and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSDEraseStartAdd(SDMMC_TypeDef *SDMMCx, uint32_t StartAdd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = (uint32_t)StartAdd;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_ERASE_GRP_START;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_ERASE_GRP_START, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the End Address Erase command for SD and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSDEraseEndAdd(SDMMC_TypeDef *SDMMCx, uint32_t EndAdd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = (uint32_t)EndAdd;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_ERASE_GRP_END;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_ERASE_GRP_END, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Start Address Erase command and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdEraseStartAdd(SDMMC_TypeDef *SDMMCx, uint32_t StartAdd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = (uint32_t)StartAdd;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE_GRP_START;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE_GRP_START, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the End Address Erase command and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdEraseEndAdd(SDMMC_TypeDef *SDMMCx, uint32_t EndAdd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = (uint32_t)EndAdd;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE_GRP_END;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE_GRP_END, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Erase command and check the response
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdErase(SDMMC_TypeDef *SDMMCx)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinit.Argument = 0U;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE, SDMMC_MAXERASETIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Stop Transfer command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdStopTransfer(SDMMC_TypeDef *SDMMCx)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Send CMD12 STOP_TRANSMISSION */
+ sdmmc_cmdinit.Argument = 0U;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_STOP_TRANSMISSION;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+
+ __SDMMC_CMDSTOP_ENABLE(SDMMCx);
+ __SDMMC_CMDTRANS_DISABLE(SDMMCx);
+
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_STOP_TRANSMISSION, SDMMC_STOPTRANSFERTIMEOUT);
+
+ __SDMMC_CMDSTOP_DISABLE(SDMMCx);
+
+ /* Ignore Address Out Of Range Error, Not relevant at end of memory */
+ if (errorstate == SDMMC_ERROR_ADDR_OUT_OF_RANGE)
+ {
+ errorstate = SDMMC_ERROR_NONE;
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Select Deselect command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param addr: Address of the card to be selected
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSelDesel(SDMMC_TypeDef *SDMMCx, uint64_t Addr)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Send CMD7 SDMMC_SEL_DESEL_CARD */
+ sdmmc_cmdinit.Argument = (uint32_t)Addr;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEL_DESEL_CARD;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEL_DESEL_CARD, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Go Idle State command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdGoIdleState(SDMMC_TypeDef *SDMMCx)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ sdmmc_cmdinit.Argument = 0U;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_GO_IDLE_STATE;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_NO;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdError(SDMMCx);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Operating Condition command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdOperCond(SDMMC_TypeDef *SDMMCx)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Send CMD8 to verify SD card interface operating condition */
+ /* Argument: - [31:12]: Reserved (shall be set to '0')
+ - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
+ - [7:0]: Check Pattern (recommended 0xAA) */
+ /* CMD Response: R7 */
+ sdmmc_cmdinit.Argument = SDMMC_CHECK_PATTERN;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SEND_EXT_CSD;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp7(SDMMCx);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Application command to verify that that the next command
+ * is an application specific com-mand rather than a standard command
+ * and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Argument: Command Argument
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdAppCommand(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ sdmmc_cmdinit.Argument = (uint32_t)Argument;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_APP_CMD;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ /* If there is a HAL_ERROR, it is a MMC card, else
+ it is a SD card: SD card 2.0 (voltage range mismatch)
+ or SD card 1.x */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_APP_CMD, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the command asking the accessed card to send its operating
+ * condition register (OCR)
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Argument: Command Argument
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdAppOperCommand(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ sdmmc_cmdinit.Argument = Argument;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_OP_COND;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp3(SDMMCx);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Bus Width command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param BusWidth: BusWidth
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdBusWidth(SDMMC_TypeDef *SDMMCx, uint32_t BusWidth)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ sdmmc_cmdinit.Argument = (uint32_t)BusWidth;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_APP_SD_SET_BUSWIDTH;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_APP_SD_SET_BUSWIDTH, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Send SCR command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSendSCR(SDMMC_TypeDef *SDMMCx)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Send CMD51 SD_APP_SEND_SCR */
+ sdmmc_cmdinit.Argument = 0U;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_SEND_SCR;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_APP_SEND_SCR, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Send CID command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSendCID(SDMMC_TypeDef *SDMMCx)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Send CMD2 ALL_SEND_CID */
+ sdmmc_cmdinit.Argument = 0U;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ALL_SEND_CID;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_LONG;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp2(SDMMCx);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Send CSD command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Argument: Command Argument
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSendCSD(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Send CMD9 SEND_CSD */
+ sdmmc_cmdinit.Argument = Argument;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_CSD;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_LONG;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp2(SDMMCx);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Send CSD command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param pRCA: Card RCA
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSetRelAdd(SDMMC_TypeDef *SDMMCx, uint16_t *pRCA)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Send CMD3 SD_CMD_SET_REL_ADDR */
+ sdmmc_cmdinit.Argument = 0U;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_REL_ADDR;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp6(SDMMCx, SDMMC_CMD_SET_REL_ADDR, pRCA);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Status command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Argument: Command Argument
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSendStatus(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ sdmmc_cmdinit.Argument = Argument;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_STATUS;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEND_STATUS, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Status register command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdStatusRegister(SDMMC_TypeDef *SDMMCx)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ sdmmc_cmdinit.Argument = 0U;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_STATUS;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_APP_STATUS, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Sends host capacity support information and activates the card's
+ * initialization process. Send SDMMC_CMD_SEND_OP_COND command
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @parame Argument: Argument used for the command
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdOpCondition(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ sdmmc_cmdinit.Argument = Argument;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_OP_COND;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp3(SDMMCx);
+
+ return errorstate;
+}
+
+/**
+ * @brief Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH comand
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @parame Argument: Argument used for the command
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSwitch(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Send CMD6 to activate SDR50 Mode and Power Limit 1.44W */
+ /* CMD Response: R1 */
+ sdmmc_cmdinit.Argument = Argument; /* SDMMC_SDR25_SWITCH_PATTERN;*/
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SWITCH;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_HS_SWITCH, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the command asking the accessed card to send its operating
+ * condition register (OCR)
+ * @param None
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdVoltageSwitch(SDMMC_TypeDef *SDMMCx)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ sdmmc_cmdinit.Argument = 0x00000000;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_VOLTAGE_SWITCH;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_VOLTAGE_SWITCH, SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+/**
+ * @brief Send the Send EXT_CSD command and check the response.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Argument: Command Argument
+ * @retval HAL status
+ */
+uint32_t SDMMC_CmdSendEXTCSD(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinit;
+ uint32_t errorstate;
+
+ /* Send CMD9 SEND_CSD */
+ sdmmc_cmdinit.Argument = Argument;
+ sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SEND_EXT_CSD;
+ sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
+ (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
+
+ /* Check for error conditions */
+ errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_HS_SEND_EXT_CSD,SDMMC_CMDTIMEOUT);
+
+ return errorstate;
+}
+
+
+/**
+ * @}
+ */
+
+/* Private function ----------------------------------------------------------*/
+/** @addtogroup SD_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Checks for error conditions for CMD0.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static uint32_t SDMMC_GetCmdError(SDMMC_TypeDef *SDMMCx)
+{
+ /* 8 is the number of required instructions cycles for the below loop statement.
+ The SDMMC_CMDTIMEOUT is expressed in ms */
+ register uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
+
+ do
+ {
+ if (count-- == 0U)
+ {
+ return SDMMC_ERROR_TIMEOUT;
+ }
+
+ }while(!__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CMDSENT));
+
+ /* Clear all the static flags */
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
+
+ return SDMMC_ERROR_NONE;
+}
+
+/**
+ * @brief Checks for error conditions for R1 response.
+ * @param hsd: SD handle
+ * @param SD_CMD: The sent command index
+ * @retval SD Card error state
+ */
+static uint32_t SDMMC_GetCmdResp1(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint32_t Timeout)
+{
+ uint32_t response_r1;
+ uint32_t sta_reg;
+
+ /* 8 is the number of required instructions cycles for the below loop statement.
+ The Timeout is expressed in ms */
+ register uint32_t count = Timeout * (SystemCoreClock / 8U /1000U);
+
+ do
+ {
+ if (count-- == 0U)
+ {
+ return SDMMC_ERROR_TIMEOUT;
+ }
+ sta_reg = SDMMCx->STA;
+ }while(((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT | SDMMC_FLAG_BUSYD0END)) == 0U) ||
+ ((sta_reg & SDMMC_FLAG_CMDACT) != 0U ));
+
+ if(__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
+ {
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
+
+ return SDMMC_ERROR_CMD_RSP_TIMEOUT;
+ }
+ else if(__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
+ {
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
+
+ return SDMMC_ERROR_CMD_CRC_FAIL;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Clear all the static flags */
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
+
+ /* Check response received is of desired command */
+ if(SDMMC_GetCommandResponse(SDMMCx) != SD_CMD)
+ {
+ return SDMMC_ERROR_CMD_CRC_FAIL;
+ }
+
+ /* We have received response, retrieve it for analysis */
+ response_r1 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
+
+ if((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO)
+ {
+ return SDMMC_ERROR_NONE;
+ }
+ else if((response_r1 & SDMMC_OCR_ADDR_OUT_OF_RANGE) == SDMMC_OCR_ADDR_OUT_OF_RANGE)
+ {
+ return SDMMC_ERROR_ADDR_OUT_OF_RANGE;
+ }
+ else if((response_r1 & SDMMC_OCR_ADDR_MISALIGNED) == SDMMC_OCR_ADDR_MISALIGNED)
+ {
+ return SDMMC_ERROR_ADDR_MISALIGNED;
+ }
+ else if((response_r1 & SDMMC_OCR_BLOCK_LEN_ERR) == SDMMC_OCR_BLOCK_LEN_ERR)
+ {
+ return SDMMC_ERROR_BLOCK_LEN_ERR;
+ }
+ else if((response_r1 & SDMMC_OCR_ERASE_SEQ_ERR) == SDMMC_OCR_ERASE_SEQ_ERR)
+ {
+ return SDMMC_ERROR_ERASE_SEQ_ERR;
+ }
+ else if((response_r1 & SDMMC_OCR_BAD_ERASE_PARAM) == SDMMC_OCR_BAD_ERASE_PARAM)
+ {
+ return SDMMC_ERROR_BAD_ERASE_PARAM;
+ }
+ else if((response_r1 & SDMMC_OCR_WRITE_PROT_VIOLATION) == SDMMC_OCR_WRITE_PROT_VIOLATION)
+ {
+ return SDMMC_ERROR_WRITE_PROT_VIOLATION;
+ }
+ else if((response_r1 & SDMMC_OCR_LOCK_UNLOCK_FAILED) == SDMMC_OCR_LOCK_UNLOCK_FAILED)
+ {
+ return SDMMC_ERROR_LOCK_UNLOCK_FAILED;
+ }
+ else if((response_r1 & SDMMC_OCR_COM_CRC_FAILED) == SDMMC_OCR_COM_CRC_FAILED)
+ {
+ return SDMMC_ERROR_COM_CRC_FAILED;
+ }
+ else if((response_r1 & SDMMC_OCR_ILLEGAL_CMD) == SDMMC_OCR_ILLEGAL_CMD)
+ {
+ return SDMMC_ERROR_ILLEGAL_CMD;
+ }
+ else if((response_r1 & SDMMC_OCR_CARD_ECC_FAILED) == SDMMC_OCR_CARD_ECC_FAILED)
+ {
+ return SDMMC_ERROR_CARD_ECC_FAILED;
+ }
+ else if((response_r1 & SDMMC_OCR_CC_ERROR) == SDMMC_OCR_CC_ERROR)
+ {
+ return SDMMC_ERROR_CC_ERR;
+ }
+ else if((response_r1 & SDMMC_OCR_STREAM_READ_UNDERRUN) == SDMMC_OCR_STREAM_READ_UNDERRUN)
+ {
+ return SDMMC_ERROR_STREAM_READ_UNDERRUN;
+ }
+ else if((response_r1 & SDMMC_OCR_STREAM_WRITE_OVERRUN) == SDMMC_OCR_STREAM_WRITE_OVERRUN)
+ {
+ return SDMMC_ERROR_STREAM_WRITE_OVERRUN;
+ }
+ else if((response_r1 & SDMMC_OCR_CID_CSD_OVERWRITE) == SDMMC_OCR_CID_CSD_OVERWRITE)
+ {
+ return SDMMC_ERROR_CID_CSD_OVERWRITE;
+ }
+ else if((response_r1 & SDMMC_OCR_WP_ERASE_SKIP) == SDMMC_OCR_WP_ERASE_SKIP)
+ {
+ return SDMMC_ERROR_WP_ERASE_SKIP;
+ }
+ else if((response_r1 & SDMMC_OCR_CARD_ECC_DISABLED) == SDMMC_OCR_CARD_ECC_DISABLED)
+ {
+ return SDMMC_ERROR_CARD_ECC_DISABLED;
+ }
+ else if((response_r1 & SDMMC_OCR_ERASE_RESET) == SDMMC_OCR_ERASE_RESET)
+ {
+ return SDMMC_ERROR_ERASE_RESET;
+ }
+ else if((response_r1 & SDMMC_OCR_AKE_SEQ_ERROR) == SDMMC_OCR_AKE_SEQ_ERROR)
+ {
+ return SDMMC_ERROR_AKE_SEQ_ERR;
+ }
+ else
+ {
+ return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
+ }
+}
+
+/**
+ * @brief Checks for error conditions for R2 (CID or CSD) response.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static uint32_t SDMMC_GetCmdResp2(SDMMC_TypeDef *SDMMCx)
+{
+ uint32_t sta_reg;
+ /* 8 is the number of required instructions cycles for the below loop statement.
+ The SDMMC_CMDTIMEOUT is expressed in ms */
+ register uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
+
+ do
+ {
+ if (count-- == 0U)
+ {
+ return SDMMC_ERROR_TIMEOUT;
+ }
+ sta_reg = SDMMCx->STA;
+ }while(((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
+ ((sta_reg & SDMMC_FLAG_CMDACT) != 0U ));
+
+ if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
+ {
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
+
+ return SDMMC_ERROR_CMD_RSP_TIMEOUT;
+ }
+ else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
+ {
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
+
+ return SDMMC_ERROR_CMD_CRC_FAIL;
+ }
+ else
+ {
+ /* No error flag set */
+ /* Clear all the static flags */
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
+ }
+
+ return SDMMC_ERROR_NONE;
+}
+
+/**
+ * @brief Checks for error conditions for R3 (OCR) response.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static uint32_t SDMMC_GetCmdResp3(SDMMC_TypeDef *SDMMCx)
+{
+ uint32_t sta_reg;
+ /* 8 is the number of required instructions cycles for the below loop statement.
+ The SDMMC_CMDTIMEOUT is expressed in ms */
+ register uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
+
+ do
+ {
+ if (count-- == 0U)
+ {
+ return SDMMC_ERROR_TIMEOUT;
+ }
+ sta_reg = SDMMCx->STA;
+ }while(((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
+ ((sta_reg & SDMMC_FLAG_CMDACT) != 0U ));
+
+ if(__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
+ {
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
+
+ return SDMMC_ERROR_CMD_RSP_TIMEOUT;
+ }
+ else
+ {
+ /* Clear all the static flags */
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
+ }
+
+ return SDMMC_ERROR_NONE;
+}
+
+/**
+ * @brief Checks for error conditions for R6 (RCA) response.
+ * @param hsd: SD handle
+ * @param SD_CMD: The sent command index
+ * @param pRCA: Pointer to the variable that will contain the SD card relative
+ * address RCA
+ * @retval SD Card error state
+ */
+static uint32_t SDMMC_GetCmdResp6(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint16_t *pRCA)
+{
+ uint32_t response_r1;
+ uint32_t sta_reg;
+
+ /* 8 is the number of required instructions cycles for the below loop statement.
+ The SDMMC_CMDTIMEOUT is expressed in ms */
+ register uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
+
+ do
+ {
+ if (count-- == 0U)
+ {
+ return SDMMC_ERROR_TIMEOUT;
+ }
+ sta_reg = SDMMCx->STA;
+ }while(((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
+ ((sta_reg & SDMMC_FLAG_CMDACT) != 0U ));
+
+ if(__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
+ {
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
+
+ return SDMMC_ERROR_CMD_RSP_TIMEOUT;
+ }
+ else if(__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
+ {
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
+
+ return SDMMC_ERROR_CMD_CRC_FAIL;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Check response received is of desired command */
+ if(SDMMC_GetCommandResponse(SDMMCx) != SD_CMD)
+ {
+ return SDMMC_ERROR_CMD_CRC_FAIL;
+ }
+
+ /* Clear all the static flags */
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
+
+ /* We have received response, retrieve it. */
+ response_r1 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
+
+ if((response_r1 & (SDMMC_R6_GENERAL_UNKNOWN_ERROR | SDMMC_R6_ILLEGAL_CMD | SDMMC_R6_COM_CRC_FAILED)) == SDMMC_ALLZERO)
+ {
+ *pRCA = (uint16_t) (response_r1 >> 16);
+
+ return SDMMC_ERROR_NONE;
+ }
+ else if((response_r1 & SDMMC_R6_ILLEGAL_CMD) == SDMMC_R6_ILLEGAL_CMD)
+ {
+ return SDMMC_ERROR_ILLEGAL_CMD;
+ }
+ else if((response_r1 & SDMMC_R6_COM_CRC_FAILED) == SDMMC_R6_COM_CRC_FAILED)
+ {
+ return SDMMC_ERROR_COM_CRC_FAILED;
+ }
+ else
+ {
+ return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
+ }
+}
+
+/**
+ * @brief Checks for error conditions for R7 response.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static uint32_t SDMMC_GetCmdResp7(SDMMC_TypeDef *SDMMCx)
+{
+ uint32_t sta_reg;
+ /* 8 is the number of required instructions cycles for the below loop statement.
+ The SDMMC_CMDTIMEOUT is expressed in ms */
+ register uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
+
+ do
+ {
+ if (count-- == 0U)
+ {
+ return SDMMC_ERROR_TIMEOUT;
+ }
+ sta_reg = SDMMCx->STA;
+ }while(((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
+ ((sta_reg & SDMMC_FLAG_CMDACT) != 0U ));
+
+ if(__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
+ {
+ /* Card is SD V2.0 compliant */
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
+
+ return SDMMC_ERROR_CMD_RSP_TIMEOUT;
+ }
+
+ else if(__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
+ {
+ /* Card is SD V2.0 compliant */
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
+
+ return SDMMC_ERROR_CMD_CRC_FAIL;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if(__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CMDREND))
+ {
+ /* Card is SD V2.0 compliant */
+ __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CMDREND);
+ }
+
+ return SDMMC_ERROR_NONE;
+
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SD_MODULE_ENABLED || HAL_MMC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_spi.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_spi.c
new file mode 100644
index 0000000000..f6cceba928
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_spi.c
@@ -0,0 +1,738 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_spi.c
+ * @author MCD Application Team
+ * @brief SPI LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_spi.h"
+#include "stm32h7xx_ll_bus.h"
+#include "stm32h7xx_ll_rcc.h"
+#ifdef GENERATOR_I2S_PRESENT
+#include "stm32h7xx_ll_rcc.h"
+#endif /* GENERATOR_I2S_PRESENT*/
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined(SPI1) || defined(SPI2) || defined(SPI3) || defined(SPI4) || defined(SPI5) || defined(SPI6)
+
+/** @addtogroup SPI_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup SPI_LL_Private_Macros
+ * @{
+ */
+
+#define IS_LL_SPI_MODE(__VALUE__) (((__VALUE__) == LL_SPI_MODE_MASTER) \
+ || ((__VALUE__) == LL_SPI_MODE_SLAVE))
+
+#define IS_LL_SPI_SS_IDLENESS(__VALUE__) (((__VALUE__) == LL_SPI_SS_IDLENESS_00CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_01CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_02CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_03CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_04CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_05CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_06CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_07CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_08CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_09CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_10CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_11CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_12CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_13CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_14CYCLE) \
+ || ((__VALUE__) == LL_SPI_SS_IDLENESS_15CYCLE))
+
+#define IS_LL_SPI_ID_IDLENESS(__VALUE__) (((__VALUE__) == LL_SPI_ID_IDLENESS_00CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_01CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_02CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_03CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_04CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_05CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_06CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_07CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_08CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_09CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_10CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_11CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_12CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_13CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_14CYCLE) \
+ || ((__VALUE__) == LL_SPI_ID_IDLENESS_15CYCLE))
+
+#define IS_LL_SPI_TXCRCINIT_PATTERN(__VALUE__) (((__VALUE__) == LL_SPI_TXCRCINIT_ALL_ZERO_PATTERN) \
+ || ((__VALUE__) == LL_SPI_TXCRCINIT_ALL_ONES_PATTERN))
+
+#define IS_LL_SPI_RXCRCINIT_PATTERN(__VALUE__) (((__VALUE__) == LL_SPI_RXCRCINIT_ALL_ZERO_PATTERN) \
+ || ((__VALUE__) == LL_SPI_RXCRCINIT_ALL_ONES_PATTERN))
+
+#define IS_LL_SPI_UDR_CONFIG_REGISTER(__VALUE__) (((__VALUE__) == LL_SPI_UDR_CONFIG_REGISTER_PATTERN) \
+ || ((__VALUE__) == LL_SPI_UDR_CONFIG_LAST_RECEIVED) \
+ || ((__VALUE__) == LL_SPI_UDR_CONFIG_LAST_TRANSMITTED))
+
+#define IS_LL_SPI_UDR_DETECT_BEGIN_DATA(__VALUE__) (((__VALUE__) == LL_SPI_UDR_DETECT_BEGIN_DATA_FRAME) \
+ || ((__VALUE__) == LL_SPI_UDR_DETECT_END_DATA_FRAME) \
+ || ((__VALUE__) == LL_SPI_UDR_DETECT_BEGIN_ACTIVE_NSS))
+
+#define IS_LL_SPI_PROTOCOL(__VALUE__) (((__VALUE__) == LL_SPI_PROTOCOL_MOTOROLA) \
+ || ((__VALUE__) == LL_SPI_PROTOCOL_TI))
+
+#define IS_LL_SPI_PHASE(__VALUE__) (((__VALUE__) == LL_SPI_PHASE_1EDGE) \
+ || ((__VALUE__) == LL_SPI_PHASE_2EDGE))
+
+#define IS_LL_SPI_POLARITY(__VALUE__) (((__VALUE__) == LL_SPI_POLARITY_LOW) \
+ || ((__VALUE__) == LL_SPI_POLARITY_HIGH))
+
+#define IS_LL_SPI_BAUDRATEPRESCALER(__VALUE__) (((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV2) \
+ || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV4) \
+ || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV8) \
+ || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV16) \
+ || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV32) \
+ || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV64) \
+ || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV128) \
+ || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV256))
+
+#define IS_LL_SPI_BITORDER(__VALUE__) (((__VALUE__) == LL_SPI_LSB_FIRST) \
+ || ((__VALUE__) == LL_SPI_MSB_FIRST))
+
+#define IS_LL_SPI_TRANSFER_DIRECTION(__VALUE__) (((__VALUE__) == LL_SPI_FULL_DUPLEX) \
+ || ((__VALUE__) == LL_SPI_SIMPLEX_TX) \
+ || ((__VALUE__) == LL_SPI_SIMPLEX_RX) \
+ || ((__VALUE__) == LL_SPI_HALF_DUPLEX_RX) \
+ || ((__VALUE__) == LL_SPI_HALF_DUPLEX_TX))
+
+#define IS_LL_SPI_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_SPI_DATAWIDTH_4BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_5BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_6BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_7BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_9BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_10BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_11BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_12BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_13BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_14BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_15BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_16BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_17BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_18BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_19BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_20BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_21BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_22BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_23BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_24BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_25BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_26BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_27BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_28BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_29BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_30BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_31BIT) \
+ || ((__VALUE__) == LL_SPI_DATAWIDTH_32BIT))
+
+#define IS_LL_SPI_FIFO_TH(__VALUE__) (((__VALUE__) == LL_SPI_FIFO_TH_01DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_02DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_03DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_04DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_05DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_06DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_07DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_08DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_09DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_10DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_11DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_12DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_13DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_14DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_15DATA) \
+ || ((__VALUE__) == LL_SPI_FIFO_TH_16DATA))
+
+#define IS_LL_SPI_CRC(__VALUE__) (((__VALUE__) == LL_SPI_CRC_4BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_5BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_6BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_7BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_8BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_9BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_10BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_11BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_12BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_13BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_14BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_15BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_16BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_17BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_18BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_19BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_20BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_21BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_22BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_23BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_24BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_25BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_26BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_27BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_28BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_29BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_30BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_31BIT) \
+ || ((__VALUE__) == LL_SPI_CRC_32BIT))
+
+#define IS_LL_SPI_NSS(__VALUE__) (((__VALUE__) == LL_SPI_NSS_SOFT) \
+ || ((__VALUE__) == LL_SPI_NSS_HARD_INPUT) \
+ || ((__VALUE__) == LL_SPI_NSS_HARD_OUTPUT))
+
+#define IS_LL_SPI_RX_FIFO(__VALUE__) (((__VALUE__) == LL_SPI_RX_FIFO_0PACKET) \
+ || ((__VALUE__) == LL_SPI_RX_FIFO_1PACKET) \
+ || ((__VALUE__) == LL_SPI_RX_FIFO_2PACKET) \
+ || ((__VALUE__) == LL_SPI_RX_FIFO_3PACKET))
+
+#define IS_LL_SPI_CRCCALCULATION(__VALUE__) (((__VALUE__) == LL_SPI_CRCCALCULATION_ENABLE) \
+ || ((__VALUE__) == LL_SPI_CRCCALCULATION_DISABLE))
+
+#define IS_LL_SPI_CRC_POLYNOMIAL(__VALUE__) ((__VALUE__) >= 0x1UL)
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup SPI_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup SPI_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize the SPI registers to their default reset values.
+ * @param SPIx SPI Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: SPI registers are de-initialized
+ * - ERROR: SPI registers are not de-initialized
+ */
+ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx)
+{
+ ErrorStatus status = ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_INSTANCE(SPIx));
+
+#if defined(SPI1)
+ if (SPIx == SPI1)
+ {
+ /* Force reset of SPI clock */
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
+
+ /* Release reset of SPI clock */
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
+
+ status = SUCCESS;
+ }
+#endif /* SPI1 */
+#if defined(SPI2)
+ if (SPIx == SPI2)
+ {
+ /* Force reset of SPI clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
+
+ /* Release reset of SPI clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
+
+ status = SUCCESS;
+ }
+#endif /* SPI2 */
+#if defined(SPI3)
+ if (SPIx == SPI3)
+ {
+ /* Force reset of SPI clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI3);
+
+ /* Release reset of SPI clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI3);
+
+ status = SUCCESS;
+ }
+#endif /* SPI3 */
+#if defined(SPI4)
+ if (SPIx == SPI4)
+ {
+ /* Force reset of SPI clock */
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI4);
+
+ /* Release reset of SPI clock */
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI4);
+
+ status = SUCCESS;
+ }
+#endif /* SPI4 */
+#if defined(SPI5)
+ if (SPIx == SPI5)
+ {
+ /* Force reset of SPI clock */
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI5);
+
+ /* Release reset of SPI clock */
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI5);
+
+ status = SUCCESS;
+ }
+#endif /* SPI5 */
+#if defined(SPI6)
+ if (SPIx == SPI6)
+ {
+ /* Force reset of SPI clock */
+ LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_SPI6);
+
+ /* Release reset of SPI clock */
+ LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_SPI6);
+
+ status = SUCCESS;
+ }
+#endif /* SPI6 */
+
+ return status;
+}
+
+/**
+ * @brief Initialize the SPI registers according to the specified parameters in SPI_InitStruct.
+ * @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0),
+ * SPI IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
+ * @param SPIx SPI Instance
+ * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
+ * @retval An ErrorStatus enumeration value. (Return always SUCCESS)
+ */
+ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct)
+{
+ ErrorStatus status = ERROR;
+ uint32_t tmp_nss;
+ uint32_t tmp_mode;
+
+ /* Check the SPI Instance SPIx*/
+ assert_param(IS_SPI_ALL_INSTANCE(SPIx));
+
+ /* Check the SPI parameters from SPI_InitStruct*/
+ assert_param(IS_LL_SPI_TRANSFER_DIRECTION(SPI_InitStruct->TransferDirection));
+ assert_param(IS_LL_SPI_MODE(SPI_InitStruct->Mode));
+ assert_param(IS_LL_SPI_DATAWIDTH(SPI_InitStruct->DataWidth));
+ assert_param(IS_LL_SPI_POLARITY(SPI_InitStruct->ClockPolarity));
+ assert_param(IS_LL_SPI_PHASE(SPI_InitStruct->ClockPhase));
+ assert_param(IS_LL_SPI_NSS(SPI_InitStruct->NSS));
+ assert_param(IS_LL_SPI_BAUDRATEPRESCALER(SPI_InitStruct->BaudRate));
+ assert_param(IS_LL_SPI_BITORDER(SPI_InitStruct->BitOrder));
+ assert_param(IS_LL_SPI_CRCCALCULATION(SPI_InitStruct->CRCCalculation));
+
+ if (LL_SPI_IsEnabled(SPIx) == 0x00000000UL)
+ {
+ /*---------------------------- SPIx CFG1 Configuration ------------------------
+ * Configure SPIx CFG1 with parameters:
+ * - Master Baud Rate : SPI_CFG1_MBR[2:0] bits
+ * - CRC Computation Enable : SPI_CFG1_CRCEN bit
+ * - Length of data frame : SPI_CFG1_DSIZE[4:0] bits
+ */
+ MODIFY_REG(SPIx->CFG1, SPI_CFG1_MBR | SPI_CFG1_CRCEN | SPI_CFG1_DSIZE,
+ SPI_InitStruct->BaudRate | SPI_InitStruct->CRCCalculation | SPI_InitStruct->DataWidth);
+
+ tmp_nss = SPI_InitStruct->NSS;
+ tmp_mode = SPI_InitStruct->Mode;
+
+ /* Checks to setup Internal SS signal level and avoid a MODF Error */
+ if ((LL_SPI_GetNSSPolarity(SPIx) == LL_SPI_NSS_POLARITY_LOW) && (tmp_nss == LL_SPI_NSS_SOFT) && (tmp_mode == LL_SPI_MODE_MASTER))
+ {
+ LL_SPI_SetInternalSSLevel(SPIx, LL_SPI_SS_LEVEL_HIGH);
+ }
+
+ /*---------------------------- SPIx CFG2 Configuration ------------------------
+ * Configure SPIx CFG2 with parameters:
+ * - NSS management : SPI_CFG2_SSM, SPI_CFG2_SSOE bits
+ * - ClockPolarity : SPI_CFG2_CPOL bit
+ * - ClockPhase : SPI_CFG2_CPHA bit
+ * - BitOrder : SPI_CFG2_LSBFRST bit
+ * - Master/Slave Mode : SPI_CFG2_MASTER bit
+ * - SPI Mode : SPI_CFG2_COMM[1:0] bits
+ */
+ MODIFY_REG(SPIx->CFG2, SPI_CFG2_SSM | SPI_CFG2_SSOE |
+ SPI_CFG2_CPOL | SPI_CFG2_CPHA |
+ SPI_CFG2_LSBFRST | SPI_CFG2_MASTER | SPI_CFG2_COMM,
+ SPI_InitStruct->NSS | SPI_InitStruct->ClockPolarity |
+ SPI_InitStruct->ClockPhase | SPI_InitStruct->BitOrder |
+ SPI_InitStruct->Mode | (SPI_InitStruct->TransferDirection & SPI_CFG2_COMM));
+
+ /*---------------------------- SPIx CR1 Configuration ------------------------
+ * Configure SPIx CR1 with parameter:
+ * - Half Duplex Direction : SPI_CR1_HDDIR bit
+ */
+ MODIFY_REG(SPIx->CR1, SPI_CR1_HDDIR, SPI_InitStruct->TransferDirection & SPI_CR1_HDDIR);
+
+ /*---------------------------- SPIx CRCPOLY Configuration ----------------------
+ * Configure SPIx CRCPOLY with parameter:
+ * - CRCPoly : CRCPOLY[31:0] bits
+ */
+ if (SPI_InitStruct->CRCCalculation == LL_SPI_CRCCALCULATION_ENABLE)
+ {
+ assert_param(IS_LL_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly));
+ LL_SPI_SetCRCPolynomial(SPIx, SPI_InitStruct->CRCPoly);
+ }
+
+ /* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */
+ CLEAR_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SMOD);
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_SPI_InitTypeDef field to default value.
+ * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct)
+{
+ /* Set SPI_InitStruct fields to default values */
+ SPI_InitStruct->TransferDirection = LL_SPI_FULL_DUPLEX;
+ SPI_InitStruct->Mode = LL_SPI_MODE_SLAVE;
+ SPI_InitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT;
+ SPI_InitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
+ SPI_InitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
+ SPI_InitStruct->NSS = LL_SPI_NSS_HARD_INPUT;
+ SPI_InitStruct->BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
+ SPI_InitStruct->BitOrder = LL_SPI_MSB_FIRST;
+ SPI_InitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
+ SPI_InitStruct->CRCPoly = 7UL;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup I2S_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @defgroup I2S_LL_Private_Constants I2S Private Constants
+ * @{
+ */
+/* I2S registers Masks */
+#define I2S_I2SCFGR_CLEAR_MASK (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | \
+ SPI_I2SCFGR_DATFMT | SPI_I2SCFGR_CKPOL | \
+ SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_MCKOE | \
+ SPI_I2SCFGR_I2SCFG | SPI_I2SCFGR_I2SMOD )
+
+/**
+ * @}
+ */
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup I2S_LL_Private_Macros I2S Private Macros
+ * @{
+ */
+
+#define IS_LL_I2S_DATAFORMAT(__VALUE__) (((__VALUE__) == LL_I2S_DATAFORMAT_16B) \
+ || ((__VALUE__) == LL_I2S_DATAFORMAT_16B_EXTENDED) \
+ || ((__VALUE__) == LL_I2S_DATAFORMAT_24B) \
+ || ((__VALUE__) == LL_I2S_DATAFORMAT_24B_LEFT_ALIGNED) \
+ || ((__VALUE__) == LL_I2S_DATAFORMAT_32B))
+
+#define IS_LL_I2S_CHANNEL_LENGTH_TYPE (__VALUE__) (((__VALUE__) == LL_I2S_SLAVE_VARIABLE_CH_LENGTH) \
+ || ((__VALUE__) == LL_I2S_SLAVE_FIXED_CH_LENGTH))
+
+#define IS_LL_I2S_CKPOL(__VALUE__) (((__VALUE__) == LL_I2S_POLARITY_LOW) \
+ || ((__VALUE__) == LL_I2S_POLARITY_HIGH))
+
+#define IS_LL_I2S_STANDARD(__VALUE__) (((__VALUE__) == LL_I2S_STANDARD_PHILIPS) \
+ || ((__VALUE__) == LL_I2S_STANDARD_MSB) \
+ || ((__VALUE__) == LL_I2S_STANDARD_LSB) \
+ || ((__VALUE__) == LL_I2S_STANDARD_PCM_SHORT) \
+ || ((__VALUE__) == LL_I2S_STANDARD_PCM_LONG))
+
+#define IS_LL_I2S_MODE(__VALUE__) (((__VALUE__) == LL_I2S_MODE_SLAVE_TX) \
+ || ((__VALUE__) == LL_I2S_MODE_SLAVE_RX) \
+ || ((__VALUE__) == LL_I2S_MODE_SLAVE_FULL_DUPLEX) \
+ || ((__VALUE__) == LL_I2S_MODE_MASTER_TX) \
+ || ((__VALUE__) == LL_I2S_MODE_MASTER_RX) \
+ || ((__VALUE__) == LL_I2S_MODE_MASTER_FULL_DUPLEX))
+
+#define IS_LL_I2S_MCLK_OUTPUT(__VALUE__) (((__VALUE__) == LL_I2S_MCLK_OUTPUT_ENABLE) \
+ || ((__VALUE__) == LL_I2S_MCLK_OUTPUT_DISABLE))
+
+#define IS_LL_I2S_AUDIO_FREQ(__VALUE__) ((((__VALUE__) >= LL_I2S_AUDIOFREQ_8K) \
+ && ((__VALUE__) <= LL_I2S_AUDIOFREQ_192K)) \
+ || ((__VALUE__) == LL_I2S_AUDIOFREQ_DEFAULT))
+
+#define IS_LL_I2S_PRESCALER_LINEAR(__VALUE__) ((__VALUE__) <= 0xFFUL)
+
+#define IS_LL_I2S_PRESCALER_PARITY(__VALUE__) (((__VALUE__) == LL_I2S_PRESCALER_PARITY_EVEN) \
+ || ((__VALUE__) == LL_I2S_PRESCALER_PARITY_ODD))
+
+#define IS_LL_I2S_FIFO_TH (__VALUE__) (((__VALUE__) == LL_I2S_LL_I2S_FIFO_TH_01DATA) \
+ || ((__VALUE__) == LL_I2S_LL_I2S_FIFO_TH_02DATA) \
+ || ((__VALUE__) == LL_I2S_LL_I2S_FIFO_TH_03DATA) \
+ || ((__VALUE__) == LL_I2S_LL_I2S_FIFO_TH_04DATA) \
+ || ((__VALUE__) == LL_I2S_LL_I2S_FIFO_TH_05DATA) \
+ || ((__VALUE__) == LL_I2S_LL_I2S_FIFO_TH_06DATA) \
+ || ((__VALUE__) == LL_I2S_LL_I2S_FIFO_TH_07DATA) \
+ || ((__VALUE__) == LL_I2S_LL_I2S_FIFO_TH_08DATA))
+
+#define IS_LL_I2S_BIT_ORDER(__VALUE__) (((__VALUE__) == LL_I2S_LSB_FIRST) \
+ || ((__VALUE__) == LL_I2S_MSB_FIRST))
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup I2S_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup I2S_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize the SPI/I2S registers to their default reset values.
+ * @param SPIx SPI Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: SPI registers are de-initialized
+ * - ERROR: SPI registers are not de-initialized
+ */
+ErrorStatus LL_I2S_DeInit(SPI_TypeDef *SPIx)
+{
+ return LL_SPI_DeInit(SPIx);
+}
+
+/**
+ * @brief Initializes the SPI/I2S registers according to the specified parameters in I2S_InitStruct.
+ * @note As some bits in I2S configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0),
+ * SPI IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
+ * @note I2S (SPI) source clock must be ready before calling this function. Otherwise will results in wrong programming.
+ * @param SPIx SPI Instance
+ * @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: SPI registers are Initialized
+ * - ERROR: SPI registers are not Initialized
+ */
+ErrorStatus LL_I2S_Init(SPI_TypeDef *SPIx, LL_I2S_InitTypeDef *I2S_InitStruct)
+{
+ uint32_t i2sdiv = 0UL, i2sodd = 0UL, packetlength = 1UL, ispcm = 0UL;
+ uint32_t tmp;
+ uint32_t sourceclock;
+ ErrorStatus status = ERROR;
+
+ /* Check the I2S parameters */
+ assert_param(IS_I2S_ALL_INSTANCE(SPIx));
+ assert_param(IS_LL_I2S_MODE(I2S_InitStruct->Mode));
+ assert_param(IS_LL_I2S_STANDARD(I2S_InitStruct->Standard));
+ assert_param(IS_LL_I2S_DATAFORMAT(I2S_InitStruct->DataFormat));
+ assert_param(IS_LL_I2S_MCLK_OUTPUT(I2S_InitStruct->MCLKOutput));
+ assert_param(IS_LL_I2S_AUDIO_FREQ(I2S_InitStruct->AudioFreq));
+ assert_param(IS_LL_I2S_CKPOL(I2S_InitStruct->ClockPolarity));
+
+ /* Check that SPE bit is set to 0 in order to be sure that SPI/I2S block is disabled.
+ * In this case, it is useless to check if the I2SMOD bit is set to 0 because
+ * this bit I2SMOD only serves to select the desired mode.
+ */
+ if (LL_SPI_IsEnabled(SPIx) == 0x00000000UL)
+ {
+ /*---------------------------- SPIx I2SCFGR Configuration --------------------
+ * Configure SPIx I2SCFGR with parameters:
+ * - Mode : SPI_I2SCFGR_I2SCFG[2:0] bits
+ * - Standard : SPI_I2SCFGR_I2SSTD[1:0] and SPI_I2SCFGR_PCMSYNC bits
+ * - DataFormat : SPI_I2SCFGR_CHLEN, SPI_I2SCFGR_DATFMT and SPI_I2SCFGR_DATLEN[1:0] bits
+ * - ClockPolarity : SPI_I2SCFGR_CKPOL bit
+ * - MCLKOutput : SPI_I2SPR_MCKOE bit
+ * - I2S mode : SPI_I2SCFGR_I2SMOD bit
+ */
+
+ /* Write to SPIx I2SCFGR */
+ MODIFY_REG(SPIx->I2SCFGR,
+ I2S_I2SCFGR_CLEAR_MASK,
+ I2S_InitStruct->Mode | I2S_InitStruct->Standard |
+ I2S_InitStruct->DataFormat | I2S_InitStruct->ClockPolarity |
+ I2S_InitStruct->MCLKOutput | SPI_I2SCFGR_I2SMOD);
+
+ /*---------------------------- SPIx I2SCFGR Configuration ----------------------
+ * Configure SPIx I2SCFGR with parameters:
+ * - AudioFreq : SPI_I2SCFGR_I2SDIV[7:0] and SPI_I2SCFGR_ODD bits
+ */
+
+ /* If the requested audio frequency is not the default, compute the prescaler (i2sodd, i2sdiv)
+ * else, default values are used: i2sodd = 0U, i2sdiv = 0U.
+ */
+ if (I2S_InitStruct->AudioFreq != LL_I2S_AUDIOFREQ_DEFAULT)
+ {
+ /* Check the frame length (For the Prescaler computing)
+ * Default value: LL_I2S_DATAFORMAT_16B (packetlength = 1U).
+ */
+ if (I2S_InitStruct->DataFormat != LL_I2S_DATAFORMAT_16B)
+ {
+ /* Packet length is 32 bits */
+ packetlength = 2UL;
+ }
+
+ /* Check if PCM standard is used */
+ if ((I2S_InitStruct->Standard == LL_I2S_STANDARD_PCM_SHORT) ||
+ (I2S_InitStruct->Standard == LL_I2S_STANDARD_PCM_LONG))
+ {
+ ispcm = 1UL;
+ }
+
+ /* Get the I2S (SPI) source clock value */
+#if defined (SPI_SPI6I2S_SUPPORT)
+ if (SPIx == SPI6)
+ {
+ sourceclock = LL_RCC_GetSPIClockFreq(LL_RCC_SPI6_CLKSOURCE);
+ }
+ else
+ {
+ sourceclock = LL_RCC_GetSPIClockFreq(LL_RCC_SPI123_CLKSOURCE);
+ }
+#else
+ sourceclock = LL_RCC_GetSPIClockFreq(LL_RCC_SPI123_CLKSOURCE);
+#endif
+
+ /* Compute the Real divider depending on the MCLK output state with a fixed point */
+ if (I2S_InitStruct->MCLKOutput == LL_I2S_MCLK_OUTPUT_ENABLE)
+ {
+ /* MCLK output is enabled */
+ tmp = (((sourceclock / (256UL >> ispcm)) * 16UL) / I2S_InitStruct->AudioFreq) + 8UL;
+ }
+ else
+ {
+ /* MCLK output is disabled */
+ tmp = (((sourceclock / ((32UL >> ispcm) * packetlength)) * 16UL) / I2S_InitStruct->AudioFreq) + 8UL;
+ }
+
+ /* Remove the fixed point */
+ tmp = tmp / 16UL;
+
+ /* Check the parity of the divider */
+ i2sodd = tmp & 0x1UL;
+
+ /* Compute the i2sdiv prescaler */
+ i2sdiv = tmp / 2UL;
+ }
+
+ /* Test if the obtain values are forbiden or out of range */
+ if (((i2sodd == 1UL) && (i2sdiv == 1UL)) || (i2sdiv > 0xFFUL))
+ {
+ /* Set the default values */
+ i2sdiv = 0UL;
+ i2sodd = 0UL;
+ }
+
+ /* Write to SPIx I2SCFGR register the computed value */
+ MODIFY_REG(SPIx->I2SCFGR,
+ SPI_I2SCFGR_ODD | SPI_I2SCFGR_I2SDIV,
+ (i2sodd << SPI_I2SCFGR_ODD_Pos) | (i2sdiv << SPI_I2SCFGR_I2SDIV_Pos));
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_I2S_InitTypeDef field to default value.
+ * @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_I2S_StructInit(LL_I2S_InitTypeDef *I2S_InitStruct)
+{
+ /*--------------- Reset I2S init structure parameters values -----------------*/
+ I2S_InitStruct->Mode = LL_I2S_MODE_SLAVE_TX;
+ I2S_InitStruct->Standard = LL_I2S_STANDARD_PHILIPS;
+ I2S_InitStruct->DataFormat = LL_I2S_DATAFORMAT_16B;
+ I2S_InitStruct->MCLKOutput = LL_I2S_MCLK_OUTPUT_DISABLE;
+ I2S_InitStruct->AudioFreq = LL_I2S_AUDIOFREQ_DEFAULT;
+ I2S_InitStruct->ClockPolarity = LL_I2S_POLARITY_LOW;
+}
+
+/**
+ * @brief Set linear and parity prescaler.
+ * @note To calculate value of PrescalerLinear(I2SDIV[7:0] bits) and PrescalerParity(ODD bit)\n
+ * Check Audio frequency table and formulas inside Reference Manual (SPI/I2S).
+ * @param SPIx SPI Instance
+ * @param PrescalerLinear Value between Min_Data=0x00 and Max_Data=0xFF
+ * @note PrescalerLinear '1' is not authorized with parity LL_I2S_PRESCALER_PARITY_ODD
+ * @param PrescalerParity This parameter can be one of the following values:
+ * @arg @ref LL_I2S_PRESCALER_PARITY_EVEN
+ * @arg @ref LL_I2S_PRESCALER_PARITY_ODD
+ * @retval None
+ */
+void LL_I2S_ConfigPrescaler(SPI_TypeDef *SPIx, uint32_t PrescalerLinear, uint32_t PrescalerParity)
+{
+ /* Check the I2S parameters */
+ assert_param(IS_I2S_ALL_INSTANCE(SPIx));
+ assert_param(IS_LL_I2S_PRESCALER_LINEAR(PrescalerLinear));
+ assert_param(IS_LL_I2S_PRESCALER_PARITY(PrescalerParity));
+
+ /* Write to SPIx I2SPR */
+ MODIFY_REG(SPIx->I2SCFGR, SPI_I2SCFGR_I2SDIV | SPI_I2SCFGR_ODD, (PrescalerLinear << SPI_I2SCFGR_I2SDIV_Pos) |
+ (PrescalerParity << SPI_I2SCFGR_ODD_Pos));
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined(SPI1) || defined(SPI2) || defined(SPI3) || defined(SPI4) || defined(SPI5) || defined(SPI6) */
+
+/**
+ * @}
+ */
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_swpmi.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_swpmi.c
new file mode 100644
index 0000000000..58b0cbc3c8
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_swpmi.c
@@ -0,0 +1,179 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_swpmi.c
+ * @author MCD Application Team
+ * @brief SWPMI LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_swpmi.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+
+/** @addtogroup SWPMI_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup SWPMI_LL_Private_Macros
+ * @{
+ */
+
+#define IS_LL_SWPMI_BITRATE_VALUE(__VALUE__) (((__VALUE__) <= 255U))
+
+#define IS_LL_SWPMI_SW_BUFFER_RX(__VALUE__) (((__VALUE__) == LL_SWPMI_SW_BUFFER_RX_SINGLE) \
+ || ((__VALUE__) == LL_SWPMI_SW_BUFFER_RX_MULTI))
+
+#define IS_LL_SWPMI_SW_BUFFER_TX(__VALUE__) (((__VALUE__) == LL_SWPMI_SW_BUFFER_TX_SINGLE) \
+ || ((__VALUE__) == LL_SWPMI_SW_BUFFER_TX_MULTI))
+
+#define IS_LL_SWPMI_VOLTAGE_CLASS(__VALUE__) (((__VALUE__) == LL_SWPMI_VOLTAGE_CLASS_C) \
+ || ((__VALUE__) == LL_SWPMI_VOLTAGE_CLASS_B))
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup SWPMI_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup SWPMI_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize the SWPMI peripheral registers to their default reset values.
+ * @param SWPMIx SWPMI Instance
+ * @retval An ErrorStatus enumeration value
+ * - SUCCESS: SWPMI registers are de-initialized
+ * - ERROR: Not applicable
+ */
+ErrorStatus LL_SWPMI_DeInit(SWPMI_TypeDef *SWPMIx)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameter */
+ assert_param(IS_SWPMI_INSTANCE(SWPMIx));
+
+ if (SWPMIx == SWPMI1)
+ {
+ LL_APB1_GRP2_ForceReset(LL_APB1_GRP2_PERIPH_SWPMI1);
+ LL_APB1_GRP2_ReleaseReset(LL_APB1_GRP2_PERIPH_SWPMI1);
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Initialize the SWPMI peripheral according to the specified parameters in the SWPMI_InitStruct.
+ * @note As some bits in SWPMI configuration registers can only be written when the SWPMI is deactivated (SWPMI_CR_SWPACT bit = 0),
+ * SWPMI IP should be in deactivated state prior calling this function. Otherwise, ERROR result will be returned.
+ * @param SWPMIx SWPMI Instance
+ * @param SWPMI_InitStruct pointer to a @ref LL_SWPMI_InitTypeDef structure that contains
+ * the configuration information for the SWPMI peripheral.
+ * @retval An ErrorStatus enumeration value
+ * - SUCCESS: SWPMI registers are initialized
+ * - ERROR: SWPMI registers are not initialized
+ */
+ErrorStatus LL_SWPMI_Init(SWPMI_TypeDef *SWPMIx, LL_SWPMI_InitTypeDef *SWPMI_InitStruct)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_SWPMI_INSTANCE(SWPMIx));
+ assert_param(IS_LL_SWPMI_BITRATE_VALUE(SWPMI_InitStruct->BitRatePrescaler));
+ assert_param(IS_LL_SWPMI_SW_BUFFER_TX(SWPMI_InitStruct->TxBufferingMode));
+ assert_param(IS_LL_SWPMI_SW_BUFFER_RX(SWPMI_InitStruct->RxBufferingMode));
+ assert_param(IS_LL_SWPMI_VOLTAGE_CLASS(SWPMI_InitStruct->VoltageClass));
+
+ /* SWPMI needs to be in deactivated state, in order to be able to configure some bits */
+ if (LL_SWPMI_IsActivated(SWPMIx) == 0U)
+ {
+ /* Configure the BRR register (Bitrate) */
+ LL_SWPMI_SetBitRatePrescaler(SWPMIx, SWPMI_InitStruct->BitRatePrescaler);
+
+ /* Configure the voltage class */
+ LL_SWPMI_SetVoltageClass(SWPMIx, SWPMI_InitStruct->VoltageClass);
+
+ /* Set the new configuration of the SWPMI peripheral */
+ MODIFY_REG(SWPMIx->CR,
+ (SWPMI_CR_RXMODE | SWPMI_CR_TXMODE),
+ (SWPMI_InitStruct->TxBufferingMode | SWPMI_InitStruct->RxBufferingMode));
+ }
+ /* Else (SWPMI not in deactivated state => return ERROR) */
+ else
+ {
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set each @ref LL_SWPMI_InitTypeDef field to default value.
+ * @param SWPMI_InitStruct pointer to a @ref LL_SWPMI_InitTypeDef structure that contains
+ * the configuration information for the SWPMI peripheral.
+ * @retval None
+ */
+void LL_SWPMI_StructInit(LL_SWPMI_InitTypeDef *SWPMI_InitStruct)
+{
+ /* Set SWPMI_InitStruct fields to default values */
+ SWPMI_InitStruct->VoltageClass = LL_SWPMI_VOLTAGE_CLASS_C;
+ SWPMI_InitStruct->BitRatePrescaler = (uint32_t)0x00000001;
+ SWPMI_InitStruct->TxBufferingMode = LL_SWPMI_SW_BUFFER_TX_SINGLE;
+ SWPMI_InitStruct->RxBufferingMode = LL_SWPMI_SW_BUFFER_RX_SINGLE;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_tim.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_tim.c
new file mode 100644
index 0000000000..a344a9ac4b
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_tim.c
@@ -0,0 +1,1380 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_tim.c
+ * @author MCD Application Team
+ * @brief TIM LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_tim.h"
+#include "stm32h7xx_ll_bus.h"
+
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (TIM1) || defined (TIM2) || defined (TIM3) || defined (TIM4) || defined (TIM5) || defined (TIM6) || defined (TIM7) || defined (TIM8) || defined (TIM12) || defined (TIM13) || defined (TIM14) || defined (TIM15) || defined (TIM16) || defined (TIM17)
+
+/** @addtogroup TIM_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup TIM_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_TIM_COUNTERMODE(__VALUE__) (((__VALUE__) == LL_TIM_COUNTERMODE_UP) \
+ || ((__VALUE__) == LL_TIM_COUNTERMODE_DOWN) \
+ || ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_UP) \
+ || ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_DOWN) \
+ || ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_UP_DOWN))
+
+#define IS_LL_TIM_CLOCKDIVISION(__VALUE__) (((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV1) \
+ || ((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV2) \
+ || ((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV4))
+
+#define IS_LL_TIM_OCMODE(__VALUE__) (((__VALUE__) == LL_TIM_OCMODE_FROZEN) \
+ || ((__VALUE__) == LL_TIM_OCMODE_ACTIVE) \
+ || ((__VALUE__) == LL_TIM_OCMODE_INACTIVE) \
+ || ((__VALUE__) == LL_TIM_OCMODE_TOGGLE) \
+ || ((__VALUE__) == LL_TIM_OCMODE_FORCED_INACTIVE) \
+ || ((__VALUE__) == LL_TIM_OCMODE_FORCED_ACTIVE) \
+ || ((__VALUE__) == LL_TIM_OCMODE_PWM1) \
+ || ((__VALUE__) == LL_TIM_OCMODE_PWM2) \
+ || ((__VALUE__) == LL_TIM_OCMODE_RETRIG_OPM1) \
+ || ((__VALUE__) == LL_TIM_OCMODE_RETRIG_OPM2) \
+ || ((__VALUE__) == LL_TIM_OCMODE_COMBINED_PWM1) \
+ || ((__VALUE__) == LL_TIM_OCMODE_COMBINED_PWM2) \
+ || ((__VALUE__) == LL_TIM_OCMODE_ASSYMETRIC_PWM1) \
+ || ((__VALUE__) == LL_TIM_OCMODE_ASSYMETRIC_PWM2))
+
+#define IS_LL_TIM_OCSTATE(__VALUE__) (((__VALUE__) == LL_TIM_OCSTATE_DISABLE) \
+ || ((__VALUE__) == LL_TIM_OCSTATE_ENABLE))
+
+#define IS_LL_TIM_OCPOLARITY(__VALUE__) (((__VALUE__) == LL_TIM_OCPOLARITY_HIGH) \
+ || ((__VALUE__) == LL_TIM_OCPOLARITY_LOW))
+
+#define IS_LL_TIM_OCIDLESTATE(__VALUE__) (((__VALUE__) == LL_TIM_OCIDLESTATE_LOW) \
+ || ((__VALUE__) == LL_TIM_OCIDLESTATE_HIGH))
+
+#define IS_LL_TIM_ACTIVEINPUT(__VALUE__) (((__VALUE__) == LL_TIM_ACTIVEINPUT_DIRECTTI) \
+ || ((__VALUE__) == LL_TIM_ACTIVEINPUT_INDIRECTTI) \
+ || ((__VALUE__) == LL_TIM_ACTIVEINPUT_TRC))
+
+#define IS_LL_TIM_ICPSC(__VALUE__) (((__VALUE__) == LL_TIM_ICPSC_DIV1) \
+ || ((__VALUE__) == LL_TIM_ICPSC_DIV2) \
+ || ((__VALUE__) == LL_TIM_ICPSC_DIV4) \
+ || ((__VALUE__) == LL_TIM_ICPSC_DIV8))
+
+#define IS_LL_TIM_IC_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_IC_FILTER_FDIV1) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N2) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N4) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N8) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV2_N6) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV2_N8) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV4_N6) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV4_N8) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV8_N6) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV8_N8) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N5) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N6) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N8) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N5) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N6) \
+ || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N8))
+
+#define IS_LL_TIM_IC_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_IC_POLARITY_RISING) \
+ || ((__VALUE__) == LL_TIM_IC_POLARITY_FALLING) \
+ || ((__VALUE__) == LL_TIM_IC_POLARITY_BOTHEDGE))
+
+#define IS_LL_TIM_ENCODERMODE(__VALUE__) (((__VALUE__) == LL_TIM_ENCODERMODE_X2_TI1) \
+ || ((__VALUE__) == LL_TIM_ENCODERMODE_X2_TI2) \
+ || ((__VALUE__) == LL_TIM_ENCODERMODE_X4_TI12))
+
+#define IS_LL_TIM_IC_POLARITY_ENCODER(__VALUE__) (((__VALUE__) == LL_TIM_IC_POLARITY_RISING) \
+ || ((__VALUE__) == LL_TIM_IC_POLARITY_FALLING))
+
+#define IS_LL_TIM_OSSR_STATE(__VALUE__) (((__VALUE__) == LL_TIM_OSSR_DISABLE) \
+ || ((__VALUE__) == LL_TIM_OSSR_ENABLE))
+
+#define IS_LL_TIM_OSSI_STATE(__VALUE__) (((__VALUE__) == LL_TIM_OSSI_DISABLE) \
+ || ((__VALUE__) == LL_TIM_OSSI_ENABLE))
+
+#define IS_LL_TIM_LOCK_LEVEL(__VALUE__) (((__VALUE__) == LL_TIM_LOCKLEVEL_OFF) \
+ || ((__VALUE__) == LL_TIM_LOCKLEVEL_1) \
+ || ((__VALUE__) == LL_TIM_LOCKLEVEL_2) \
+ || ((__VALUE__) == LL_TIM_LOCKLEVEL_3))
+
+#define IS_LL_TIM_BREAK_STATE(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_DISABLE) \
+ || ((__VALUE__) == LL_TIM_BREAK_ENABLE))
+
+#define IS_LL_TIM_BREAK_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_POLARITY_LOW) \
+ || ((__VALUE__) == LL_TIM_BREAK_POLARITY_HIGH))
+
+#define IS_LL_TIM_BREAK_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1_N2) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1_N4) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV2_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV2_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV4_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV4_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV8_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV8_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV16_N5) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV16_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV16_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV32_N5) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV32_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV32_N8))
+
+#define IS_LL_TIM_BREAK2_STATE(__VALUE__) (((__VALUE__) == LL_TIM_BREAK2_DISABLE) \
+ || ((__VALUE__) == LL_TIM_BREAK2_ENABLE))
+
+#define IS_LL_TIM_BREAK2_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_BREAK2_POLARITY_LOW) \
+ || ((__VALUE__) == LL_TIM_BREAK2_POLARITY_HIGH))
+
+#define IS_LL_TIM_BREAK2_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1_N2) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1_N4) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV2_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV2_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV4_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV4_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV8_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV8_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV16_N5) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV16_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV16_N8) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV32_N5) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV32_N6) \
+ || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV32_N8))
+
+#define IS_LL_TIM_AUTOMATIC_OUTPUT_STATE(__VALUE__) (((__VALUE__) == LL_TIM_AUTOMATICOUTPUT_DISABLE) \
+ || ((__VALUE__) == LL_TIM_AUTOMATICOUTPUT_ENABLE))
+/**
+ * @}
+ */
+
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup TIM_LL_Private_Functions TIM Private Functions
+ * @{
+ */
+static ErrorStatus OC1Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
+static ErrorStatus OC2Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
+static ErrorStatus OC3Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
+static ErrorStatus OC4Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
+static ErrorStatus OC5Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
+static ErrorStatus OC6Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
+static ErrorStatus IC1Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
+static ErrorStatus IC2Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
+static ErrorStatus IC3Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
+static ErrorStatus IC4Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup TIM_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup TIM_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief Set TIMx registers to their reset values.
+ * @param TIMx Timer instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: invalid TIMx instance
+ */
+ErrorStatus LL_TIM_DeInit(TIM_TypeDef *TIMx)
+{
+ ErrorStatus result = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(TIMx));
+
+ if (TIMx == TIM1)
+ {
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM1);
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM1);
+ }
+#if defined(TIM2)
+ else if (TIMx == TIM2)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM2);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM2);
+ }
+#endif
+#if defined(TIM3)
+ else if (TIMx == TIM3)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM3);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM3);
+ }
+#endif
+#if defined(TIM4)
+ else if (TIMx == TIM4)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM4);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM4);
+ }
+#endif
+#if defined(TIM5)
+ else if (TIMx == TIM5)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM5);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM5);
+ }
+#endif
+#if defined(TIM6)
+ else if (TIMx == TIM6)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM6);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM6);
+ }
+#endif
+#if defined (TIM7)
+ else if (TIMx == TIM7)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM7);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM7);
+ }
+#endif
+#if defined(TIM8)
+ else if (TIMx == TIM8)
+ {
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM8);
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM8);
+ }
+#endif
+#if defined(TIM12)
+ else if (TIMx == TIM12)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM12);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM12);
+ }
+#endif
+#if defined(TIM13)
+ else if (TIMx == TIM13)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM13);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM13);
+ }
+#endif
+#if defined(TIM14)
+ else if (TIMx == TIM14)
+ {
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM14);
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM14);
+ }
+#endif
+#if defined(TIM15)
+ else if (TIMx == TIM15)
+ {
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM15);
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM15);
+ }
+#endif
+#if defined(TIM16)
+ else if (TIMx == TIM16)
+ {
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM16);
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM16);
+ }
+#endif
+#if defined(TIM17)
+ else if (TIMx == TIM17)
+ {
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM17);
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM17);
+ }
+#endif
+ else
+ {
+ result = ERROR;
+ }
+
+ return result;
+}
+
+/**
+ * @brief Set the fields of the time base unit configuration data structure
+ * to their default values.
+ * @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure (time base unit configuration data structure)
+ * @retval None
+ */
+void LL_TIM_StructInit(LL_TIM_InitTypeDef *TIM_InitStruct)
+{
+ /* Set the default configuration */
+ TIM_InitStruct->Prescaler = (uint16_t)0x0000;
+ TIM_InitStruct->CounterMode = LL_TIM_COUNTERMODE_UP;
+ TIM_InitStruct->Autoreload = 0xFFFFFFFFU;
+ TIM_InitStruct->ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
+ TIM_InitStruct->RepetitionCounter = 0x00000000U;
+}
+
+/**
+ * @brief Configure the TIMx time base unit.
+ * @param TIMx Timer Instance
+ * @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure (TIMx time base unit configuration data structure)
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_TIM_Init(TIM_TypeDef *TIMx, LL_TIM_InitTypeDef *TIM_InitStruct)
+{
+ uint32_t tmpcr1;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_COUNTERMODE(TIM_InitStruct->CounterMode));
+ assert_param(IS_LL_TIM_CLOCKDIVISION(TIM_InitStruct->ClockDivision));
+
+ tmpcr1 = LL_TIM_ReadReg(TIMx, CR1);
+
+ if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx))
+ {
+ /* Select the Counter Mode */
+ MODIFY_REG(tmpcr1, (TIM_CR1_DIR | TIM_CR1_CMS), TIM_InitStruct->CounterMode);
+ }
+
+ if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
+ {
+ /* Set the clock division */
+ MODIFY_REG(tmpcr1, TIM_CR1_CKD, TIM_InitStruct->ClockDivision);
+ }
+
+ /* Write to TIMx CR1 */
+ LL_TIM_WriteReg(TIMx, CR1, tmpcr1);
+
+ /* Set the Autoreload value */
+ LL_TIM_SetAutoReload(TIMx, TIM_InitStruct->Autoreload);
+
+ /* Set the Prescaler value */
+ LL_TIM_SetPrescaler(TIMx, TIM_InitStruct->Prescaler);
+
+ if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))
+ {
+ /* Set the Repetition Counter value */
+ LL_TIM_SetRepetitionCounter(TIMx, TIM_InitStruct->RepetitionCounter);
+ }
+
+ /* Generate an update event to reload the Prescaler
+ and the repetition counter value (if applicable) immediately */
+ LL_TIM_GenerateEvent_UPDATE(TIMx);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Set the fields of the TIMx output channel configuration data
+ * structure to their default values.
+ * @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure (the output channel configuration data structure)
+ * @retval None
+ */
+void LL_TIM_OC_StructInit(LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct)
+{
+ /* Set the default configuration */
+ TIM_OC_InitStruct->OCMode = LL_TIM_OCMODE_FROZEN;
+ TIM_OC_InitStruct->OCState = LL_TIM_OCSTATE_DISABLE;
+ TIM_OC_InitStruct->OCNState = LL_TIM_OCSTATE_DISABLE;
+ TIM_OC_InitStruct->CompareValue = 0x00000000U;
+ TIM_OC_InitStruct->OCPolarity = LL_TIM_OCPOLARITY_HIGH;
+ TIM_OC_InitStruct->OCNPolarity = LL_TIM_OCPOLARITY_HIGH;
+ TIM_OC_InitStruct->OCIdleState = LL_TIM_OCIDLESTATE_LOW;
+ TIM_OC_InitStruct->OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
+}
+
+/**
+ * @brief Configure the TIMx output channel.
+ * @param TIMx Timer Instance
+ * @param Channel This parameter can be one of the following values:
+ * @arg @ref LL_TIM_CHANNEL_CH1
+ * @arg @ref LL_TIM_CHANNEL_CH2
+ * @arg @ref LL_TIM_CHANNEL_CH3
+ * @arg @ref LL_TIM_CHANNEL_CH4
+ * @arg @ref LL_TIM_CHANNEL_CH5
+ * @arg @ref LL_TIM_CHANNEL_CH6
+ * @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure (TIMx output channel configuration data structure)
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx output channel is initialized
+ * - ERROR: TIMx output channel is not initialized
+ */
+ErrorStatus LL_TIM_OC_Init(TIM_TypeDef *TIMx, uint32_t Channel, LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct)
+{
+ ErrorStatus result = ERROR;
+
+ switch (Channel)
+ {
+ case LL_TIM_CHANNEL_CH1:
+ result = OC1Config(TIMx, TIM_OC_InitStruct);
+ break;
+ case LL_TIM_CHANNEL_CH2:
+ result = OC2Config(TIMx, TIM_OC_InitStruct);
+ break;
+ case LL_TIM_CHANNEL_CH3:
+ result = OC3Config(TIMx, TIM_OC_InitStruct);
+ break;
+ case LL_TIM_CHANNEL_CH4:
+ result = OC4Config(TIMx, TIM_OC_InitStruct);
+ break;
+ case LL_TIM_CHANNEL_CH5:
+ result = OC5Config(TIMx, TIM_OC_InitStruct);
+ break;
+ case LL_TIM_CHANNEL_CH6:
+ result = OC6Config(TIMx, TIM_OC_InitStruct);
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+/**
+ * @brief Set the fields of the TIMx input channel configuration data
+ * structure to their default values.
+ * @param TIM_ICInitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (the input channel configuration data structure)
+ * @retval None
+ */
+void LL_TIM_IC_StructInit(LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
+{
+ /* Set the default configuration */
+ TIM_ICInitStruct->ICPolarity = LL_TIM_IC_POLARITY_RISING;
+ TIM_ICInitStruct->ICActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI;
+ TIM_ICInitStruct->ICPrescaler = LL_TIM_ICPSC_DIV1;
+ TIM_ICInitStruct->ICFilter = LL_TIM_IC_FILTER_FDIV1;
+}
+
+/**
+ * @brief Configure the TIMx input channel.
+ * @param TIMx Timer Instance
+ * @param Channel This parameter can be one of the following values:
+ * @arg @ref LL_TIM_CHANNEL_CH1
+ * @arg @ref LL_TIM_CHANNEL_CH2
+ * @arg @ref LL_TIM_CHANNEL_CH3
+ * @arg @ref LL_TIM_CHANNEL_CH4
+ * @param TIM_IC_InitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (TIMx input channel configuration data structure)
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx output channel is initialized
+ * - ERROR: TIMx output channel is not initialized
+ */
+ErrorStatus LL_TIM_IC_Init(TIM_TypeDef *TIMx, uint32_t Channel, LL_TIM_IC_InitTypeDef *TIM_IC_InitStruct)
+{
+ ErrorStatus result = ERROR;
+
+ switch (Channel)
+ {
+ case LL_TIM_CHANNEL_CH1:
+ result = IC1Config(TIMx, TIM_IC_InitStruct);
+ break;
+ case LL_TIM_CHANNEL_CH2:
+ result = IC2Config(TIMx, TIM_IC_InitStruct);
+ break;
+ case LL_TIM_CHANNEL_CH3:
+ result = IC3Config(TIMx, TIM_IC_InitStruct);
+ break;
+ case LL_TIM_CHANNEL_CH4:
+ result = IC4Config(TIMx, TIM_IC_InitStruct);
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+/**
+ * @brief Fills each TIM_EncoderInitStruct field with its default value
+ * @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (encoder interface configuration data structure)
+ * @retval None
+ */
+void LL_TIM_ENCODER_StructInit(LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct)
+{
+ /* Set the default configuration */
+ TIM_EncoderInitStruct->EncoderMode = LL_TIM_ENCODERMODE_X2_TI1;
+ TIM_EncoderInitStruct->IC1Polarity = LL_TIM_IC_POLARITY_RISING;
+ TIM_EncoderInitStruct->IC1ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI;
+ TIM_EncoderInitStruct->IC1Prescaler = LL_TIM_ICPSC_DIV1;
+ TIM_EncoderInitStruct->IC1Filter = LL_TIM_IC_FILTER_FDIV1;
+ TIM_EncoderInitStruct->IC2Polarity = LL_TIM_IC_POLARITY_RISING;
+ TIM_EncoderInitStruct->IC2ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI;
+ TIM_EncoderInitStruct->IC2Prescaler = LL_TIM_ICPSC_DIV1;
+ TIM_EncoderInitStruct->IC2Filter = LL_TIM_IC_FILTER_FDIV1;
+}
+
+/**
+ * @brief Configure the encoder interface of the timer instance.
+ * @param TIMx Timer Instance
+ * @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (TIMx encoder interface configuration data structure)
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_TIM_ENCODER_Init(TIM_TypeDef *TIMx, LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_ENCODERMODE(TIM_EncoderInitStruct->EncoderMode));
+ assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_EncoderInitStruct->IC1Polarity));
+ assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_EncoderInitStruct->IC1ActiveInput));
+ assert_param(IS_LL_TIM_ICPSC(TIM_EncoderInitStruct->IC1Prescaler));
+ assert_param(IS_LL_TIM_IC_FILTER(TIM_EncoderInitStruct->IC1Filter));
+ assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_EncoderInitStruct->IC2Polarity));
+ assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_EncoderInitStruct->IC2ActiveInput));
+ assert_param(IS_LL_TIM_ICPSC(TIM_EncoderInitStruct->IC2Prescaler));
+ assert_param(IS_LL_TIM_IC_FILTER(TIM_EncoderInitStruct->IC2Filter));
+
+ /* Disable the CC1 and CC2: Reset the CC1E and CC2E Bits */
+ TIMx->CCER &= (uint32_t)~(TIM_CCER_CC1E | TIM_CCER_CC2E);
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
+
+ /* Get the TIMx CCER register value */
+ tmpccer = LL_TIM_ReadReg(TIMx, CCER);
+
+ /* Configure TI1 */
+ tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC);
+ tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1ActiveInput >> 16U);
+ tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1Filter >> 16U);
+ tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1Prescaler >> 16U);
+
+ /* Configure TI2 */
+ tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC2S | TIM_CCMR1_IC2F | TIM_CCMR1_IC2PSC);
+ tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2ActiveInput >> 8U);
+ tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2Filter >> 8U);
+ tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2Prescaler >> 8U);
+
+ /* Set TI1 and TI2 polarity and enable TI1 and TI2 */
+ tmpccer &= (uint32_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP | TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ tmpccer |= (uint32_t)(TIM_EncoderInitStruct->IC1Polarity);
+ tmpccer |= (uint32_t)(TIM_EncoderInitStruct->IC2Polarity << 4U);
+ tmpccer |= (uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E);
+
+ /* Set encoder mode */
+ LL_TIM_SetEncoderMode(TIMx, TIM_EncoderInitStruct->EncoderMode);
+
+ /* Write to TIMx CCMR1 */
+ LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
+
+ /* Write to TIMx CCER */
+ LL_TIM_WriteReg(TIMx, CCER, tmpccer);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Set the fields of the TIMx Hall sensor interface configuration data
+ * structure to their default values.
+ * @param TIM_HallSensorInitStruct pointer to a @ref LL_TIM_HALLSENSOR_InitTypeDef structure (HALL sensor interface configuration data structure)
+ * @retval None
+ */
+void LL_TIM_HALLSENSOR_StructInit(LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct)
+{
+ /* Set the default configuration */
+ TIM_HallSensorInitStruct->IC1Polarity = LL_TIM_IC_POLARITY_RISING;
+ TIM_HallSensorInitStruct->IC1Prescaler = LL_TIM_ICPSC_DIV1;
+ TIM_HallSensorInitStruct->IC1Filter = LL_TIM_IC_FILTER_FDIV1;
+ TIM_HallSensorInitStruct->CommutationDelay = 0U;
+}
+
+/**
+ * @brief Configure the Hall sensor interface of the timer instance.
+ * @note TIMx CH1, CH2 and CH3 inputs connected through a XOR
+ * to the TI1 input channel
+ * @note TIMx slave mode controller is configured in reset mode.
+ Selected internal trigger is TI1F_ED.
+ * @note Channel 1 is configured as input, IC1 is mapped on TRC.
+ * @note Captured value stored in TIMx_CCR1 correspond to the time elapsed
+ * between 2 changes on the inputs. It gives information about motor speed.
+ * @note Channel 2 is configured in output PWM 2 mode.
+ * @note Compare value stored in TIMx_CCR2 corresponds to the commutation delay.
+ * @note OC2REF is selected as trigger output on TRGO.
+ * @note LL_TIM_IC_POLARITY_BOTHEDGE must not be used for TI1 when it is used
+ * when TIMx operates in Hall sensor interface mode.
+ * @param TIMx Timer Instance
+ * @param TIM_HallSensorInitStruct pointer to a @ref LL_TIM_HALLSENSOR_InitTypeDef structure (TIMx HALL sensor interface configuration data structure)
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_TIM_HALLSENSOR_Init(TIM_TypeDef *TIMx, LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct)
+{
+ uint32_t tmpcr2;
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_HallSensorInitStruct->IC1Polarity));
+ assert_param(IS_LL_TIM_ICPSC(TIM_HallSensorInitStruct->IC1Prescaler));
+ assert_param(IS_LL_TIM_IC_FILTER(TIM_HallSensorInitStruct->IC1Filter));
+
+ /* Disable the CC1 and CC2: Reset the CC1E and CC2E Bits */
+ TIMx->CCER &= (uint32_t)~(TIM_CCER_CC1E | TIM_CCER_CC2E);
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
+
+ /* Get the TIMx CCER register value */
+ tmpccer = LL_TIM_ReadReg(TIMx, CCER);
+
+ /* Get the TIMx SMCR register value */
+ tmpsmcr = LL_TIM_ReadReg(TIMx, SMCR);
+
+ /* Connect TIMx_CH1, CH2 and CH3 pins to the TI1 input */
+ tmpcr2 |= TIM_CR2_TI1S;
+
+ /* OC2REF signal is used as trigger output (TRGO) */
+ tmpcr2 |= LL_TIM_TRGO_OC2REF;
+
+ /* Configure the slave mode controller */
+ tmpsmcr &= (uint32_t)~(TIM_SMCR_TS | TIM_SMCR_SMS);
+ tmpsmcr |= LL_TIM_TS_TI1F_ED;
+ tmpsmcr |= LL_TIM_SLAVEMODE_RESET;
+
+ /* Configure input channel 1 */
+ tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC);
+ tmpccmr1 |= (uint32_t)(LL_TIM_ACTIVEINPUT_TRC >> 16U);
+ tmpccmr1 |= (uint32_t)(TIM_HallSensorInitStruct->IC1Filter >> 16U);
+ tmpccmr1 |= (uint32_t)(TIM_HallSensorInitStruct->IC1Prescaler >> 16U);
+
+ /* Configure input channel 2 */
+ tmpccmr1 &= (uint32_t)~(TIM_CCMR1_OC2M | TIM_CCMR1_OC2FE | TIM_CCMR1_OC2PE | TIM_CCMR1_OC2CE);
+ tmpccmr1 |= (uint32_t)(LL_TIM_OCMODE_PWM2 << 8U);
+
+ /* Set Channel 1 polarity and enable Channel 1 and Channel2 */
+ tmpccer &= (uint32_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP | TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ tmpccer |= (uint32_t)(TIM_HallSensorInitStruct->IC1Polarity);
+ tmpccer |= (uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E);
+
+ /* Write to TIMx CR2 */
+ LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
+
+ /* Write to TIMx SMCR */
+ LL_TIM_WriteReg(TIMx, SMCR, tmpsmcr);
+
+ /* Write to TIMx CCMR1 */
+ LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
+
+ /* Write to TIMx CCER */
+ LL_TIM_WriteReg(TIMx, CCER, tmpccer);
+
+ /* Write to TIMx CCR2 */
+ LL_TIM_OC_SetCompareCH2(TIMx, TIM_HallSensorInitStruct->CommutationDelay);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Set the fields of the Break and Dead Time configuration data structure
+ * to their default values.
+ * @param TIM_BDTRInitStruct pointer to a @ref LL_TIM_BDTR_InitTypeDef structure (Break and Dead Time configuration data structure)
+ * @retval None
+ */
+void LL_TIM_BDTR_StructInit(LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct)
+{
+ /* Set the default configuration */
+ TIM_BDTRInitStruct->OSSRState = LL_TIM_OSSR_DISABLE;
+ TIM_BDTRInitStruct->OSSIState = LL_TIM_OSSI_DISABLE;
+ TIM_BDTRInitStruct->LockLevel = LL_TIM_LOCKLEVEL_OFF;
+ TIM_BDTRInitStruct->DeadTime = (uint8_t)0x00;
+ TIM_BDTRInitStruct->BreakState = LL_TIM_BREAK_DISABLE;
+ TIM_BDTRInitStruct->BreakPolarity = LL_TIM_BREAK_POLARITY_LOW;
+ TIM_BDTRInitStruct->BreakFilter = LL_TIM_BREAK_FILTER_FDIV1;
+ TIM_BDTRInitStruct->Break2State = LL_TIM_BREAK2_DISABLE;
+ TIM_BDTRInitStruct->Break2Polarity = LL_TIM_BREAK2_POLARITY_LOW;
+ TIM_BDTRInitStruct->Break2Filter = LL_TIM_BREAK2_FILTER_FDIV1;
+ TIM_BDTRInitStruct->AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE;
+}
+
+/**
+ * @brief Configure the Break and Dead Time feature of the timer instance.
+ * @note As the bits BK2P, BK2E, BK2F[3:0], BKF[3:0], AOE, BKP, BKE, OSSI, OSSR
+ * and DTG[7:0] can be write-locked depending on the LOCK configuration, it
+ * can be necessary to configure all of them during the first write access to
+ * the TIMx_BDTR register.
+ * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not
+ * a timer instance provides a break input.
+ * @note Macro IS_TIM_BKIN2_INSTANCE(TIMx) can be used to check whether or not
+ * a timer instance provides a second break input.
+ * @param TIMx Timer Instance
+ * @param TIM_BDTRInitStruct pointer to a @ref LL_TIM_BDTR_InitTypeDef structure (Break and Dead Time configuration data structure)
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: Break and Dead Time is initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_TIM_BDTR_Init(TIM_TypeDef *TIMx, LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct)
+{
+ uint32_t tmpbdtr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_BREAK_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_OSSR_STATE(TIM_BDTRInitStruct->OSSRState));
+ assert_param(IS_LL_TIM_OSSI_STATE(TIM_BDTRInitStruct->OSSIState));
+ assert_param(IS_LL_TIM_LOCK_LEVEL(TIM_BDTRInitStruct->LockLevel));
+ assert_param(IS_LL_TIM_BREAK_STATE(TIM_BDTRInitStruct->BreakState));
+ assert_param(IS_LL_TIM_BREAK_POLARITY(TIM_BDTRInitStruct->BreakPolarity));
+ assert_param(IS_LL_TIM_AUTOMATIC_OUTPUT_STATE(TIM_BDTRInitStruct->AutomaticOutput));
+
+ /* 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, TIM_BDTRInitStruct->DeadTime);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, TIM_BDTRInitStruct->LockLevel);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, TIM_BDTRInitStruct->OSSIState);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, TIM_BDTRInitStruct->OSSRState);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, TIM_BDTRInitStruct->BreakState);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, TIM_BDTRInitStruct->BreakPolarity);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, TIM_BDTRInitStruct->AutomaticOutput);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_MOE, TIM_BDTRInitStruct->AutomaticOutput);
+ if (IS_TIM_ADVANCED_INSTANCE(TIMx))
+ {
+ assert_param(IS_LL_TIM_BREAK_FILTER(TIM_BDTRInitStruct->BreakFilter));
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, TIM_BDTRInitStruct->BreakFilter);
+ }
+
+ if (IS_TIM_BKIN2_INSTANCE(TIMx))
+ {
+ assert_param(IS_LL_TIM_BREAK2_STATE(TIM_BDTRInitStruct->Break2State));
+ assert_param(IS_LL_TIM_BREAK2_POLARITY(TIM_BDTRInitStruct->Break2Polarity));
+ assert_param(IS_LL_TIM_BREAK2_FILTER(TIM_BDTRInitStruct->Break2Filter));
+
+ /* Set the BREAK2 input related BDTR bit-fields */
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (TIM_BDTRInitStruct->Break2Filter));
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, TIM_BDTRInitStruct->Break2State);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, TIM_BDTRInitStruct->Break2Polarity);
+ }
+
+ /* Set TIMx_BDTR */
+ LL_TIM_WriteReg(TIMx, BDTR, tmpbdtr);
+
+ return SUCCESS;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup TIM_LL_Private_Functions TIM Private Functions
+ * @brief Private functions
+ * @{
+ */
+/**
+ * @brief Configure the TIMx output channel 1.
+ * @param TIMx Timer Instance
+ * @param TIM_OCInitStruct pointer to the the TIMx output channel 1 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus OC1Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
+
+ /* Disable the Channel 1: Reset the CC1E Bit */
+ CLEAR_BIT(TIMx->CCER, TIM_CCER_CC1E);
+
+ /* Get the TIMx CCER register value */
+ tmpccer = LL_TIM_ReadReg(TIMx, CCER);
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
+
+ /* Reset Capture/Compare selection Bits */
+ CLEAR_BIT(tmpccmr1, TIM_CCMR1_CC1S);
+
+ /* Set the Output Compare Mode */
+ MODIFY_REG(tmpccmr1, TIM_CCMR1_OC1M, TIM_OCInitStruct->OCMode);
+
+ /* Set the Output Compare Polarity */
+ MODIFY_REG(tmpccer, TIM_CCER_CC1P, TIM_OCInitStruct->OCPolarity);
+
+ /* Set the Output State */
+ MODIFY_REG(tmpccer, TIM_CCER_CC1E, TIM_OCInitStruct->OCState);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
+
+ /* Set the complementary output Polarity */
+ MODIFY_REG(tmpccer, TIM_CCER_CC1NP, TIM_OCInitStruct->OCNPolarity << 2U);
+
+ /* Set the complementary output State */
+ MODIFY_REG(tmpccer, TIM_CCER_CC1NE, TIM_OCInitStruct->OCNState << 2U);
+
+ /* Set the Output Idle state */
+ MODIFY_REG(tmpcr2, TIM_CR2_OIS1, TIM_OCInitStruct->OCIdleState);
+
+ /* Set the complementary output Idle state */
+ MODIFY_REG(tmpcr2, TIM_CR2_OIS1N, TIM_OCInitStruct->OCNIdleState << 1U);
+ }
+
+ /* Write to TIMx CR2 */
+ LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
+
+ /* Write to TIMx CCMR1 */
+ LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
+
+ /* Set the Capture Compare Register value */
+ LL_TIM_OC_SetCompareCH1(TIMx, TIM_OCInitStruct->CompareValue);
+
+ /* Write to TIMx CCER */
+ LL_TIM_WriteReg(TIMx, CCER, tmpccer);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Configure the TIMx output channel 2.
+ * @param TIMx Timer Instance
+ * @param TIM_OCInitStruct pointer to the the TIMx output channel 2 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus OC2Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
+
+ /* Disable the Channel 2: Reset the CC2E Bit */
+ CLEAR_BIT(TIMx->CCER, TIM_CCER_CC2E);
+
+ /* Get the TIMx CCER register value */
+ tmpccer = LL_TIM_ReadReg(TIMx, CCER);
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
+
+ /* Reset Capture/Compare selection Bits */
+ CLEAR_BIT(tmpccmr1, TIM_CCMR1_CC2S);
+
+ /* Select the Output Compare Mode */
+ MODIFY_REG(tmpccmr1, TIM_CCMR1_OC2M, TIM_OCInitStruct->OCMode << 8U);
+
+ /* Set the Output Compare Polarity */
+ MODIFY_REG(tmpccer, TIM_CCER_CC2P, TIM_OCInitStruct->OCPolarity << 4U);
+
+ /* Set the Output State */
+ MODIFY_REG(tmpccer, TIM_CCER_CC2E, TIM_OCInitStruct->OCState << 4U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
+
+ /* Set the complementary output Polarity */
+ MODIFY_REG(tmpccer, TIM_CCER_CC2NP, TIM_OCInitStruct->OCNPolarity << 6U);
+
+ /* Set the complementary output State */
+ MODIFY_REG(tmpccer, TIM_CCER_CC2NE, TIM_OCInitStruct->OCNState << 6U);
+
+ /* Set the Output Idle state */
+ MODIFY_REG(tmpcr2, TIM_CR2_OIS2, TIM_OCInitStruct->OCIdleState << 2U);
+
+ /* Set the complementary output Idle state */
+ MODIFY_REG(tmpcr2, TIM_CR2_OIS2N, TIM_OCInitStruct->OCNIdleState << 3U);
+ }
+
+ /* Write to TIMx CR2 */
+ LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
+
+ /* Write to TIMx CCMR1 */
+ LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
+
+ /* Set the Capture Compare Register value */
+ LL_TIM_OC_SetCompareCH2(TIMx, TIM_OCInitStruct->CompareValue);
+
+ /* Write to TIMx CCER */
+ LL_TIM_WriteReg(TIMx, CCER, tmpccer);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Configure the TIMx output channel 3.
+ * @param TIMx Timer Instance
+ * @param TIM_OCInitStruct pointer to the the TIMx output channel 3 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus OC3Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
+{
+ uint32_t tmpccmr2;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC3_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
+
+ /* Disable the Channel 3: Reset the CC3E Bit */
+ CLEAR_BIT(TIMx->CCER, TIM_CCER_CC3E);
+
+ /* Get the TIMx CCER register value */
+ tmpccer = LL_TIM_ReadReg(TIMx, CCER);
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
+
+ /* Get the TIMx CCMR2 register value */
+ tmpccmr2 = LL_TIM_ReadReg(TIMx, CCMR2);
+
+ /* Reset Capture/Compare selection Bits */
+ CLEAR_BIT(tmpccmr2, TIM_CCMR2_CC3S);
+
+ /* Select the Output Compare Mode */
+ MODIFY_REG(tmpccmr2, TIM_CCMR2_OC3M, TIM_OCInitStruct->OCMode);
+
+ /* Set the Output Compare Polarity */
+ MODIFY_REG(tmpccer, TIM_CCER_CC3P, TIM_OCInitStruct->OCPolarity << 8U);
+
+ /* Set the Output State */
+ MODIFY_REG(tmpccer, TIM_CCER_CC3E, TIM_OCInitStruct->OCState << 8U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
+
+ /* Set the complementary output Polarity */
+ MODIFY_REG(tmpccer, TIM_CCER_CC3NP, TIM_OCInitStruct->OCNPolarity << 10U);
+
+ /* Set the complementary output State */
+ MODIFY_REG(tmpccer, TIM_CCER_CC3NE, TIM_OCInitStruct->OCNState << 10U);
+
+ /* Set the Output Idle state */
+ MODIFY_REG(tmpcr2, TIM_CR2_OIS3, TIM_OCInitStruct->OCIdleState << 4U);
+
+ /* Set the complementary output Idle state */
+ MODIFY_REG(tmpcr2, TIM_CR2_OIS3N, TIM_OCInitStruct->OCNIdleState << 5U);
+ }
+
+ /* Write to TIMx CR2 */
+ LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
+
+ /* Write to TIMx CCMR2 */
+ LL_TIM_WriteReg(TIMx, CCMR2, tmpccmr2);
+
+ /* Set the Capture Compare Register value */
+ LL_TIM_OC_SetCompareCH3(TIMx, TIM_OCInitStruct->CompareValue);
+
+ /* Write to TIMx CCER */
+ LL_TIM_WriteReg(TIMx, CCER, tmpccer);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Configure the TIMx output channel 4.
+ * @param TIMx Timer Instance
+ * @param TIM_OCInitStruct pointer to the the TIMx output channel 4 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus OC4Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
+{
+ uint32_t tmpccmr2;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC4_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
+
+ /* Disable the Channel 4: Reset the CC4E Bit */
+ CLEAR_BIT(TIMx->CCER, TIM_CCER_CC4E);
+
+ /* Get the TIMx CCER register value */
+ tmpccer = LL_TIM_ReadReg(TIMx, CCER);
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
+
+ /* Get the TIMx CCMR2 register value */
+ tmpccmr2 = LL_TIM_ReadReg(TIMx, CCMR2);
+
+ /* Reset Capture/Compare selection Bits */
+ CLEAR_BIT(tmpccmr2, TIM_CCMR2_CC4S);
+
+ /* Select the Output Compare Mode */
+ MODIFY_REG(tmpccmr2, TIM_CCMR2_OC4M, TIM_OCInitStruct->OCMode << 8U);
+
+ /* Set the Output Compare Polarity */
+ MODIFY_REG(tmpccer, TIM_CCER_CC4P, TIM_OCInitStruct->OCPolarity << 12U);
+
+ /* Set the Output State */
+ MODIFY_REG(tmpccer, TIM_CCER_CC4E, TIM_OCInitStruct->OCState << 12U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
+
+ /* Set the Output Idle state */
+ MODIFY_REG(tmpcr2, TIM_CR2_OIS4, TIM_OCInitStruct->OCIdleState << 6U);
+ }
+
+ /* Write to TIMx CR2 */
+ LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
+
+ /* Write to TIMx CCMR2 */
+ LL_TIM_WriteReg(TIMx, CCMR2, tmpccmr2);
+
+ /* Set the Capture Compare Register value */
+ LL_TIM_OC_SetCompareCH4(TIMx, TIM_OCInitStruct->CompareValue);
+
+ /* Write to TIMx CCER */
+ LL_TIM_WriteReg(TIMx, CCER, tmpccer);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Configure the TIMx output channel 5.
+ * @param TIMx Timer Instance
+ * @param TIM_OCInitStruct pointer to the the TIMx output channel 5 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus OC5Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
+{
+ uint32_t tmpccmr3;
+ uint32_t tmpccer;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC5_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
+
+ /* Disable the Channel 5: Reset the CC5E Bit */
+ CLEAR_BIT(TIMx->CCER, TIM_CCER_CC5E);
+
+ /* Get the TIMx CCER register value */
+ tmpccer = LL_TIM_ReadReg(TIMx, CCER);
+
+ /* Get the TIMx CCMR3 register value */
+ tmpccmr3 = LL_TIM_ReadReg(TIMx, CCMR3);
+
+ /* Select the Output Compare Mode */
+ MODIFY_REG(tmpccmr3, TIM_CCMR3_OC5M, TIM_OCInitStruct->OCMode);
+
+ /* Set the Output Compare Polarity */
+ MODIFY_REG(tmpccer, TIM_CCER_CC5P, TIM_OCInitStruct->OCPolarity << 16U);
+
+ /* Set the Output State */
+ MODIFY_REG(tmpccer, TIM_CCER_CC5E, TIM_OCInitStruct->OCState << 16U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
+
+ /* Set the Output Idle state */
+ MODIFY_REG(TIMx->CR2, TIM_CR2_OIS5, TIM_OCInitStruct->OCIdleState << 8U);
+
+ }
+
+ /* Write to TIMx CCMR3 */
+ LL_TIM_WriteReg(TIMx, CCMR3, tmpccmr3);
+
+ /* Set the Capture Compare Register value */
+ LL_TIM_OC_SetCompareCH5(TIMx, TIM_OCInitStruct->CompareValue);
+
+ /* Write to TIMx CCER */
+ LL_TIM_WriteReg(TIMx, CCER, tmpccer);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Configure the TIMx output channel 6.
+ * @param TIMx Timer Instance
+ * @param TIM_OCInitStruct pointer to the the TIMx output channel 6 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus OC6Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
+{
+ uint32_t tmpccmr3;
+ uint32_t tmpccer;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC6_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
+ assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
+ assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
+
+ /* Disable the Channel 5: Reset the CC6E Bit */
+ CLEAR_BIT(TIMx->CCER, TIM_CCER_CC6E);
+
+ /* Get the TIMx CCER register value */
+ tmpccer = LL_TIM_ReadReg(TIMx, CCER);
+
+ /* Get the TIMx CCMR3 register value */
+ tmpccmr3 = LL_TIM_ReadReg(TIMx, CCMR3);
+
+ /* Select the Output Compare Mode */
+ MODIFY_REG(tmpccmr3, TIM_CCMR3_OC6M, TIM_OCInitStruct->OCMode << 8U);
+
+ /* Set the Output Compare Polarity */
+ MODIFY_REG(tmpccer, TIM_CCER_CC6P, TIM_OCInitStruct->OCPolarity << 20U);
+
+ /* Set the Output State */
+ MODIFY_REG(tmpccer, TIM_CCER_CC6E, TIM_OCInitStruct->OCState << 20U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
+ assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
+
+ /* Set the Output Idle state */
+ MODIFY_REG(TIMx->CR2, TIM_CR2_OIS6, TIM_OCInitStruct->OCIdleState << 10U);
+ }
+
+ /* Write to TIMx CCMR3 */
+ LL_TIM_WriteReg(TIMx, CCMR3, tmpccmr3);
+
+ /* Set the Capture Compare Register value */
+ LL_TIM_OC_SetCompareCH6(TIMx, TIM_OCInitStruct->CompareValue);
+
+ /* Write to TIMx CCER */
+ LL_TIM_WriteReg(TIMx, CCER, tmpccer);
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Configure the TIMx input channel 1.
+ * @param TIMx Timer Instance
+ * @param TIM_ICInitStruct pointer to the the TIMx input channel 1 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus IC1Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
+ assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
+ assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
+ assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
+
+ /* Disable the Channel 1: Reset the CC1E Bit */
+ TIMx->CCER &= (uint32_t)~TIM_CCER_CC1E;
+
+ /* Select the Input and set the filter and the prescaler value */
+ MODIFY_REG(TIMx->CCMR1,
+ (TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC),
+ (TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 16U);
+
+ /* Select the Polarity and set the CC1E Bit */
+ MODIFY_REG(TIMx->CCER,
+ (TIM_CCER_CC1P | TIM_CCER_CC1NP),
+ (TIM_ICInitStruct->ICPolarity | TIM_CCER_CC1E));
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Configure the TIMx input channel 2.
+ * @param TIMx Timer Instance
+ * @param TIM_ICInitStruct pointer to the the TIMx input channel 2 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus IC2Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
+ assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
+ assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
+ assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
+
+ /* Disable the Channel 2: Reset the CC2E Bit */
+ TIMx->CCER &= (uint32_t)~TIM_CCER_CC2E;
+
+ /* Select the Input and set the filter and the prescaler value */
+ MODIFY_REG(TIMx->CCMR1,
+ (TIM_CCMR1_CC2S | TIM_CCMR1_IC2F | TIM_CCMR1_IC2PSC),
+ (TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 8U);
+
+ /* Select the Polarity and set the CC2E Bit */
+ MODIFY_REG(TIMx->CCER,
+ (TIM_CCER_CC2P | TIM_CCER_CC2NP),
+ ((TIM_ICInitStruct->ICPolarity << 4U) | TIM_CCER_CC2E));
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Configure the TIMx input channel 3.
+ * @param TIMx Timer Instance
+ * @param TIM_ICInitStruct pointer to the the TIMx input channel 3 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus IC3Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CC3_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
+ assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
+ assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
+ assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
+
+ /* Disable the Channel 3: Reset the CC3E Bit */
+ TIMx->CCER &= (uint32_t)~TIM_CCER_CC3E;
+
+ /* Select the Input and set the filter and the prescaler value */
+ MODIFY_REG(TIMx->CCMR2,
+ (TIM_CCMR2_CC3S | TIM_CCMR2_IC3F | TIM_CCMR2_IC3PSC),
+ (TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 16U);
+
+ /* Select the Polarity and set the CC3E Bit */
+ MODIFY_REG(TIMx->CCER,
+ (TIM_CCER_CC3P | TIM_CCER_CC3NP),
+ ((TIM_ICInitStruct->ICPolarity << 8U) | TIM_CCER_CC3E));
+
+ return SUCCESS;
+}
+
+/**
+ * @brief Configure the TIMx input channel 4.
+ * @param TIMx Timer Instance
+ * @param TIM_ICInitStruct pointer to the the TIMx input channel 4 configuration data structure
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: TIMx registers are de-initialized
+ * - ERROR: not applicable
+ */
+static ErrorStatus IC4Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CC4_INSTANCE(TIMx));
+ assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
+ assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
+ assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
+ assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
+
+ /* Disable the Channel 4: Reset the CC4E Bit */
+ TIMx->CCER &= (uint32_t)~TIM_CCER_CC4E;
+
+ /* Select the Input and set the filter and the prescaler value */
+ MODIFY_REG(TIMx->CCMR2,
+ (TIM_CCMR2_CC4S | TIM_CCMR2_IC4F | TIM_CCMR2_IC4PSC),
+ (TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 8U);
+
+ /* Select the Polarity and set the CC2E Bit */
+ MODIFY_REG(TIMx->CCER,
+ (TIM_CCER_CC4P | TIM_CCER_CC4NP),
+ ((TIM_ICInitStruct->ICPolarity << 12U) | TIM_CCER_CC4E));
+
+ return SUCCESS;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* TIM1 || TIM2 || TIM3 || TIM4 || TIM5 || TIM6 || TIM7 || TIM8 || TIM12 || TIM13 ||TIM14 || TIM15 || TIM16 || TIM17 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_usart.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_usart.c
new file mode 100644
index 0000000000..9419620a12
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_usart.c
@@ -0,0 +1,496 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_usart.c
+ * @author MCD Application Team
+ * @brief USART LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_usart.h"
+#include "stm32h7xx_ll_rcc.h"
+#include "stm32h7xx_ll_bus.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+#if defined (USART1) || defined (USART2) || defined (USART3) || defined (USART6) || defined (UART4) || defined (UART5) || defined (UART7) || defined (UART8) || defined (UART9) || defined (USART10)
+
+/** @addtogroup USART_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup USART_LL_Private_Macros
+ * @{
+ */
+
+#define IS_LL_USART_PRESCALER(__VALUE__) (((__VALUE__) == LL_USART_PRESCALER_DIV1) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV2) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV4) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV6) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV8) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV10) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV12) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV16) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV32) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV64) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV128) \
+ || ((__VALUE__) == LL_USART_PRESCALER_DIV256))
+
+/* __BAUDRATE__ The maximum Baud Rate is derived from the maximum clock available
+ * divided by the smallest oversampling used on the USART (i.e. 8) */
+#define IS_LL_USART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) <= 12500000U)
+
+/* __VALUE__ In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. */
+#define IS_LL_USART_BRR_MIN(__VALUE__) ((__VALUE__) >= 16U)
+
+/* __VALUE__ BRR content must be lower than or equal to 0xFFFF. */
+#define IS_LL_USART_BRR_MAX(__VALUE__) ((__VALUE__) <= 0x0000FFFFU)
+
+#define IS_LL_USART_DIRECTION(__VALUE__) (((__VALUE__) == LL_USART_DIRECTION_NONE) \
+ || ((__VALUE__) == LL_USART_DIRECTION_RX) \
+ || ((__VALUE__) == LL_USART_DIRECTION_TX) \
+ || ((__VALUE__) == LL_USART_DIRECTION_TX_RX))
+
+#define IS_LL_USART_PARITY(__VALUE__) (((__VALUE__) == LL_USART_PARITY_NONE) \
+ || ((__VALUE__) == LL_USART_PARITY_EVEN) \
+ || ((__VALUE__) == LL_USART_PARITY_ODD))
+
+#define IS_LL_USART_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_USART_DATAWIDTH_7B) \
+ || ((__VALUE__) == LL_USART_DATAWIDTH_8B) \
+ || ((__VALUE__) == LL_USART_DATAWIDTH_9B))
+
+#define IS_LL_USART_OVERSAMPLING(__VALUE__) (((__VALUE__) == LL_USART_OVERSAMPLING_16) \
+ || ((__VALUE__) == LL_USART_OVERSAMPLING_8))
+
+#define IS_LL_USART_LASTBITCLKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_LASTCLKPULSE_NO_OUTPUT) \
+ || ((__VALUE__) == LL_USART_LASTCLKPULSE_OUTPUT))
+
+#define IS_LL_USART_CLOCKPHASE(__VALUE__) (((__VALUE__) == LL_USART_PHASE_1EDGE) \
+ || ((__VALUE__) == LL_USART_PHASE_2EDGE))
+
+#define IS_LL_USART_CLOCKPOLARITY(__VALUE__) (((__VALUE__) == LL_USART_POLARITY_LOW) \
+ || ((__VALUE__) == LL_USART_POLARITY_HIGH))
+
+#define IS_LL_USART_CLOCKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_CLOCK_DISABLE) \
+ || ((__VALUE__) == LL_USART_CLOCK_ENABLE))
+
+#define IS_LL_USART_STOPBITS(__VALUE__) (((__VALUE__) == LL_USART_STOPBITS_0_5) \
+ || ((__VALUE__) == LL_USART_STOPBITS_1) \
+ || ((__VALUE__) == LL_USART_STOPBITS_1_5) \
+ || ((__VALUE__) == LL_USART_STOPBITS_2))
+
+#define IS_LL_USART_HWCONTROL(__VALUE__) (((__VALUE__) == LL_USART_HWCONTROL_NONE) \
+ || ((__VALUE__) == LL_USART_HWCONTROL_RTS) \
+ || ((__VALUE__) == LL_USART_HWCONTROL_CTS) \
+ || ((__VALUE__) == LL_USART_HWCONTROL_RTS_CTS))
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup USART_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup USART_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief De-initialize USART registers (Registers restored to their default values).
+ * @param USARTx USART Instance
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: USART registers are de-initialized
+ * - ERROR: USART registers are not de-initialized
+ */
+ErrorStatus LL_USART_DeInit(USART_TypeDef *USARTx)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check the parameters */
+ assert_param(IS_UART_INSTANCE(USARTx));
+
+ if (USARTx == USART1)
+ {
+ /* Force reset of USART clock */
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_USART1);
+
+ /* Release reset of USART clock */
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_USART1);
+ }
+ else if (USARTx == USART2)
+ {
+ /* Force reset of USART clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART2);
+
+ /* Release reset of USART clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART2);
+ }
+ else if (USARTx == USART3)
+ {
+ /* Force reset of USART clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART3);
+
+ /* Release reset of USART clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART3);
+ }
+ else if (USARTx == UART4)
+ {
+ /* Force reset of UART clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART4);
+
+ /* Release reset of UART clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART4);
+ }
+ else if (USARTx == UART5)
+ {
+ /* Force reset of UART clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART5);
+
+ /* Release reset of UART clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART5);
+ }
+ else if (USARTx == USART6)
+ {
+ /* Force reset of USART clock */
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_USART6);
+
+ /* Release reset of USART clock */
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_USART6);
+ }
+ else if (USARTx == UART7)
+ {
+ /* Force reset of UART clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART7);
+
+ /* Release reset of UART clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART7);
+ }
+ else if (USARTx == UART8)
+ {
+ /* Force reset of UART clock */
+ LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART8);
+
+ /* Release reset of UART clock */
+ LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART8);
+ }
+#if defined(UART9)
+ else if (USARTx == UART9)
+ {
+ /* Force reset of UART clock */
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_UART9);
+
+ /* Release reset of UART clock */
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_UART9);
+ }
+#endif /* UART9 */
+#if defined(USART10)
+ else if (USARTx == USART10)
+ {
+ /* Force reset of USART clock */
+ LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_USART10);
+
+ /* Release reset of USART clock */
+ LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_USART10);
+ }
+#endif /* USART10 */
+ else
+ {
+ status = ERROR;
+ }
+
+ return (status);
+}
+
+/**
+ * @brief Initialize USART registers according to the specified
+ * parameters in USART_InitStruct.
+ * @note As some bits in USART configuration registers can only be written when the USART is disabled (USART_CR1_UE bit =0),
+ * USART Peripheral should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
+ * @note Baud rate value stored in USART_InitStruct BaudRate field, should be valid (different from 0).
+ * @param USARTx USART Instance
+ * @param USART_InitStruct pointer to a LL_USART_InitTypeDef structure
+ * that contains the configuration information for the specified USART peripheral.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: USART registers are initialized according to USART_InitStruct content
+ * - ERROR: Problem occurred during USART Registers initialization
+ */
+ErrorStatus LL_USART_Init(USART_TypeDef *USARTx, LL_USART_InitTypeDef *USART_InitStruct)
+{
+ ErrorStatus status = ERROR;
+ uint32_t periphclk = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ /* Check the parameters */
+ assert_param(IS_UART_INSTANCE(USARTx));
+ assert_param(IS_LL_USART_PRESCALER(USART_InitStruct->PrescalerValue));
+ assert_param(IS_LL_USART_BAUDRATE(USART_InitStruct->BaudRate));
+ assert_param(IS_LL_USART_DATAWIDTH(USART_InitStruct->DataWidth));
+ assert_param(IS_LL_USART_STOPBITS(USART_InitStruct->StopBits));
+ assert_param(IS_LL_USART_PARITY(USART_InitStruct->Parity));
+ assert_param(IS_LL_USART_DIRECTION(USART_InitStruct->TransferDirection));
+ assert_param(IS_LL_USART_HWCONTROL(USART_InitStruct->HardwareFlowControl));
+ assert_param(IS_LL_USART_OVERSAMPLING(USART_InitStruct->OverSampling));
+
+ /* USART needs to be in disabled state, in order to be able to configure some bits in
+ CRx registers */
+ if (LL_USART_IsEnabled(USARTx) == 0U)
+ {
+ /*---------------------------- USART CR1 Configuration ---------------------
+ * Configure USARTx CR1 (USART Word Length, Parity, Mode and Oversampling bits) with parameters:
+ * - DataWidth: USART_CR1_M bits according to USART_InitStruct->DataWidth value
+ * - Parity: USART_CR1_PCE, USART_CR1_PS bits according to USART_InitStruct->Parity value
+ * - TransferDirection: USART_CR1_TE, USART_CR1_RE bits according to USART_InitStruct->TransferDirection value
+ * - Oversampling: USART_CR1_OVER8 bit according to USART_InitStruct->OverSampling value.
+ */
+ MODIFY_REG(USARTx->CR1,
+ (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS |
+ USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8),
+ (USART_InitStruct->DataWidth | USART_InitStruct->Parity |
+ USART_InitStruct->TransferDirection | USART_InitStruct->OverSampling));
+
+ /*---------------------------- USART CR2 Configuration ---------------------
+ * Configure USARTx CR2 (Stop bits) with parameters:
+ * - Stop Bits: USART_CR2_STOP bits according to USART_InitStruct->StopBits value.
+ * - CLKEN, CPOL, CPHA and LBCL bits are to be configured using LL_USART_ClockInit().
+ */
+ LL_USART_SetStopBitsLength(USARTx, USART_InitStruct->StopBits);
+
+ /*---------------------------- USART CR3 Configuration ---------------------
+ * Configure USARTx CR3 (Hardware Flow Control) with parameters:
+ * - HardwareFlowControl: USART_CR3_RTSE, USART_CR3_CTSE bits according to USART_InitStruct->HardwareFlowControl value.
+ */
+ LL_USART_SetHWFlowCtrl(USARTx, USART_InitStruct->HardwareFlowControl);
+
+ /*---------------------------- USART BRR Configuration ---------------------
+ * Retrieve Clock frequency used for USART Peripheral
+ */
+ if (USARTx == USART1)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART16_CLKSOURCE);
+ }
+ else if (USARTx == USART2)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART234578_CLKSOURCE);
+ }
+ else if (USARTx == USART3)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART234578_CLKSOURCE);
+ }
+ else if (USARTx == UART4)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART234578_CLKSOURCE);
+ }
+ else if (USARTx == UART5)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART234578_CLKSOURCE);
+ }
+ else if (USARTx == USART6)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART16_CLKSOURCE);
+ }
+ else if (USARTx == UART7)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART234578_CLKSOURCE);
+ }
+ else if (USARTx == UART8)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART234578_CLKSOURCE);
+ }
+#if defined(UART9)
+ else if (USARTx == UART9)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART16_CLKSOURCE);
+ }
+#endif /* UART9 */
+#if defined(USART10)
+ else if (USARTx == USART10)
+ {
+ periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART16_CLKSOURCE);
+ }
+#endif /* USART10 */
+ else
+ {
+ /* Nothing to do, as error code is already assigned to ERROR value */
+ }
+
+ /* Configure the USART Baud Rate :
+ - prescaler value is required
+ - valid baud rate value (different from 0) is required
+ - Peripheral clock as returned by RCC service, should be valid (different from 0).
+ */
+ if ((periphclk != LL_RCC_PERIPH_FREQUENCY_NO)
+ && (USART_InitStruct->BaudRate != 0U))
+ {
+ status = SUCCESS;
+ LL_USART_SetBaudRate(USARTx,
+ periphclk,
+ USART_InitStruct->PrescalerValue,
+ USART_InitStruct->OverSampling,
+ USART_InitStruct->BaudRate);
+
+ /* Check BRR is greater than or equal to 16d */
+ assert_param(IS_LL_USART_BRR_MIN(USARTx->BRR));
+
+ /* Check BRR is lower than or equal to 0xFFFF */
+ assert_param(IS_LL_USART_BRR_MAX(USARTx->BRR));
+ }
+
+ /*---------------------------- USART PRESC Configuration -----------------------
+ * Configure USARTx PRESC (Prescaler) with parameters:
+ * - PrescalerValue: USART_PRESC_PRESCALER bits according to USART_InitStruct->PrescalerValue value.
+ */
+ LL_USART_SetPrescaler(USARTx, USART_InitStruct->PrescalerValue);
+ }
+ /* Endif (=> USART not in Disabled state => return ERROR) */
+
+ return (status);
+}
+
+/**
+ * @brief Set each @ref LL_USART_InitTypeDef field to default value.
+ * @param USART_InitStruct pointer to a @ref LL_USART_InitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+
+void LL_USART_StructInit(LL_USART_InitTypeDef *USART_InitStruct)
+{
+ /* Set USART_InitStruct fields to default values */
+ USART_InitStruct->PrescalerValue = LL_USART_PRESCALER_DIV1;
+ USART_InitStruct->BaudRate = 9600U;
+ USART_InitStruct->DataWidth = LL_USART_DATAWIDTH_8B;
+ USART_InitStruct->StopBits = LL_USART_STOPBITS_1;
+ USART_InitStruct->Parity = LL_USART_PARITY_NONE ;
+ USART_InitStruct->TransferDirection = LL_USART_DIRECTION_TX_RX;
+ USART_InitStruct->HardwareFlowControl = LL_USART_HWCONTROL_NONE;
+ USART_InitStruct->OverSampling = LL_USART_OVERSAMPLING_16;
+}
+
+/**
+ * @brief Initialize USART Clock related settings according to the
+ * specified parameters in the USART_ClockInitStruct.
+ * @note As some bits in USART configuration registers can only be written when the USART is disabled (USART_CR1_UE bit =0),
+ * USART Peripheral should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
+ * @param USARTx USART Instance
+ * @param USART_ClockInitStruct pointer to a @ref LL_USART_ClockInitTypeDef structure
+ * that contains the Clock configuration information for the specified USART peripheral.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: USART registers related to Clock settings are initialized according to USART_ClockInitStruct content
+ * - ERROR: Problem occurred during USART Registers initialization
+ */
+ErrorStatus LL_USART_ClockInit(USART_TypeDef *USARTx, LL_USART_ClockInitTypeDef *USART_ClockInitStruct)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check USART Instance and Clock signal output parameters */
+ assert_param(IS_UART_INSTANCE(USARTx));
+ assert_param(IS_LL_USART_CLOCKOUTPUT(USART_ClockInitStruct->ClockOutput));
+
+ /* USART needs to be in disabled state, in order to be able to configure some bits in
+ CRx registers */
+ if (LL_USART_IsEnabled(USARTx) == 0U)
+ {
+ /*---------------------------- USART CR2 Configuration -----------------------*/
+ /* If Clock signal has to be output */
+ if (USART_ClockInitStruct->ClockOutput == LL_USART_CLOCK_DISABLE)
+ {
+ /* Deactivate Clock signal delivery :
+ * - Disable Clock Output: USART_CR2_CLKEN cleared
+ */
+ LL_USART_DisableSCLKOutput(USARTx);
+ }
+ else
+ {
+ /* Ensure USART instance is USART capable */
+ assert_param(IS_USART_INSTANCE(USARTx));
+
+ /* Check clock related parameters */
+ assert_param(IS_LL_USART_CLOCKPOLARITY(USART_ClockInitStruct->ClockPolarity));
+ assert_param(IS_LL_USART_CLOCKPHASE(USART_ClockInitStruct->ClockPhase));
+ assert_param(IS_LL_USART_LASTBITCLKOUTPUT(USART_ClockInitStruct->LastBitClockPulse));
+
+ /*---------------------------- USART CR2 Configuration -----------------------
+ * Configure USARTx CR2 (Clock signal related bits) with parameters:
+ * - Enable Clock Output: USART_CR2_CLKEN set
+ * - Clock Polarity: USART_CR2_CPOL bit according to USART_ClockInitStruct->ClockPolarity value
+ * - Clock Phase: USART_CR2_CPHA bit according to USART_ClockInitStruct->ClockPhase value
+ * - Last Bit Clock Pulse Output: USART_CR2_LBCL bit according to USART_ClockInitStruct->LastBitClockPulse value.
+ */
+ MODIFY_REG(USARTx->CR2,
+ USART_CR2_CLKEN | USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_LBCL,
+ USART_CR2_CLKEN | USART_ClockInitStruct->ClockPolarity |
+ USART_ClockInitStruct->ClockPhase | USART_ClockInitStruct->LastBitClockPulse);
+ }
+ }
+ /* Else (USART not in Disabled state => return ERROR */
+ else
+ {
+ status = ERROR;
+ }
+
+ return (status);
+}
+
+/**
+ * @brief Set each field of a @ref LL_USART_ClockInitTypeDef type structure to default value.
+ * @param USART_ClockInitStruct pointer to a @ref LL_USART_ClockInitTypeDef structure
+ * whose fields will be set to default values.
+ * @retval None
+ */
+void LL_USART_ClockStructInit(LL_USART_ClockInitTypeDef *USART_ClockInitStruct)
+{
+ /* Set LL_USART_ClockInitStruct fields with default values */
+ USART_ClockInitStruct->ClockOutput = LL_USART_CLOCK_DISABLE;
+ USART_ClockInitStruct->ClockPolarity = LL_USART_POLARITY_LOW; /* Not relevant when ClockOutput = LL_USART_CLOCK_DISABLE */
+ USART_ClockInitStruct->ClockPhase = LL_USART_PHASE_1EDGE; /* Not relevant when ClockOutput = LL_USART_CLOCK_DISABLE */
+ USART_ClockInitStruct->LastBitClockPulse = LL_USART_LASTCLKPULSE_NO_OUTPUT; /* Not relevant when ClockOutput = LL_USART_CLOCK_DISABLE */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* USART1 || USART2 || USART3 || USART6 || UART4 || UART5 || UART7 || UART8 || UART9 || USART10 */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_usb.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_usb.c
new file mode 100644
index 0000000000..1e4ae32fd1
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_usb.c
@@ -0,0 +1,1989 @@
+/**
+ ******************************************************************************
+ * @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
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Fill parameters of Init structure in USB_OTG_CfgTypeDef structure.
+
+ (#) Call USB_CoreInit() API to initialize the USB Core peripheral.
+
+ (#) The upper HAL HCD/PCD driver will call the right routines for its internal processes.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* 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 and set Host mode */
+ 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)
+ {
+ USBx->GAHBCFG |= USB_OTG_GAHBCFG_HBSTLEN_2;
+ 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
+ * @arg USB_DRD_MODE: Dual Role Device mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx, USB_OTG_ModeTypeDef mode)
+{
+ USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD);
+
+ if (mode == USB_HOST_MODE)
+ {
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD;
+ }
+ else if (mode == USB_DEVICE_MODE)
+ {
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+ HAL_Delay(50U);
+
+ 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;
+
+ /* Device mode configuration */
+ USBx_DEVICE->DCFG |= DCFG_FRAME_INTERVAL_80;
+
+ 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_OTG_FlushTxFifo : Flush a Tx FIFO
+ * @param USBx Selected device
+ * @param num FIFO number
+ * This parameter can be a value from 1 to 15
+ 15 means Flush all Tx FIFOs
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_FlushTxFifo(USB_OTG_GlobalTypeDef *USBx, uint32_t num)
+{
+ uint32_t count = 0U;
+
+ USBx->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (num << 6));
+
+ do
+ {
+ if (++count > 200000U)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_FlushRxFifo : Flush Rx FIFO
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t count = 0;
+
+ USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
+
+ do
+ {
+ if (++count > 200000U)
+ {
+ 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(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 PCD_SPEED_HIGH: High speed mode
+ * @arg PCD_SPEED_FULL: Full speed mode
+ */
+uint8_t USB_GetDevSpeed(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;
+}
+
+/**
+ * @brief Activate and configure an endpoint
+ * @param USBx Selected device
+ * @param ep pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
+{
+ 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(USB_OTG_GlobalTypeDef *USBx, 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(USB_OTG_GlobalTypeDef *USBx, 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)
+ {
+ 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
+ {
+ 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(USB_OTG_GlobalTypeDef *USBx, 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)
+ {
+ USBx_INEP(epnum)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP;
+ USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
+ }
+ else
+ {
+ 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 & (1U << 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);
+ USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket) << 19));
+ USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len);
+
+ if (ep->type == EP_TYPE_ISOC)
+ {
+ USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT);
+ USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1U << 29));
+ }
+ }
+
+ 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 & (1U << 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 & (1U << 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 (ep->xfer_len == 0U)
+ {
+ USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->maxpacket);
+ USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
+ }
+ else
+ {
+ pktcnt = (uint16_t)((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket);
+ USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_PKTCNT & ((uint32_t)pktcnt << 19);
+ USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket * pktcnt);
+ }
+
+ 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 & (1U << 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_EP0StartXfer : setup and starts a transfer over the EP 0
+ * @param USBx Selected device
+ * @param ep pointer to endpoint structure
+ * @param dma USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep, uint8_t dma)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t epnum = (uint32_t)ep->num;
+
+ /* 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 & (1U << 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 (ep->xfer_len > ep->maxpacket)
+ {
+ ep->xfer_len = ep->maxpacket;
+ }
+ USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19));
+ 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);
+ }
+
+ /* 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);
+
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ if (ep->xfer_len > 0U)
+ {
+ USBx_DEVICE->DIEPEMPMSK |= 1UL << (ep->num & EP_ADDR_MSK);
+ }
+ }
+ }
+ 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 (ep->xfer_len > 0U)
+ {
+ ep->xfer_len = ep->maxpacket;
+ }
+
+ USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
+ USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket));
+
+ if (dma == 1U)
+ {
+ if ((uint32_t)ep->xfer_buff != 0U)
+ {
+ USBx_OUTEP(epnum)->DOEPDMA = (uint32_t)(ep->xfer_buff);
+ }
+ }
+
+ /* EP enable */
+ USBx_OUTEP(epnum)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_WritePacket : Writes a packet into the Tx FIFO associated
+ * with the EP/channel
+ * @param USBx Selected device
+ * @param src pointer to source buffer
+ * @param ch_ep_num endpoint or host channel number
+ * @param len Number of bytes to write
+ * @param dma USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len, uint8_t dma)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t *pSrc = (uint32_t *)src;
+ uint32_t count32b, 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++;
+ }
+ }
+
+ 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(USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t *pDest = (uint32_t *)dest;
+ uint32_t i;
+ uint32_t count32b = ((uint32_t)len + 3U) / 4U;
+
+ for (i = 0U; i < count32b; i++)
+ {
+ __UNALIGNED_UINT32_WRITE(pDest, USBx_DFIFO(0U));
+ pDest++;
+ }
+
+ return ((void *)pDest);
+}
+
+/**
+ * @brief USB_EPSetStall : set a stall condition over an EP
+ * @param USBx Selected device
+ * @param ep pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EPSetStall(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
+{
+ 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(USB_OTG_GlobalTypeDef *USBx, 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;
+}
+
+/**
+ * @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(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 the pull-up/pull-down
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DevConnect(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS;
+ HAL_Delay(3U);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DevDisconnect : Disconnect the USB device by disabling the pull-up/pull-down
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DevDisconnect(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;
+ HAL_Delay(3U);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_ReadInterrupts: return the global USB interrupt status
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+uint32_t USB_ReadInterrupts(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t tmpreg;
+
+ tmpreg = USBx->GINTSTS;
+ tmpreg &= USBx->GINTMSK;
+
+ return tmpreg;
+}
+
+/**
+ * @brief USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+uint32_t USB_ReadDevAllOutEpInterrupt(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t 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 HAL status
+ */
+uint32_t USB_ReadDevAllInEpInterrupt(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(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(USB_OTG_GlobalTypeDef *USBx, uint8_t epnum)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t tmpreg, msk, 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 interrupt flag
+ * @retval None
+ */
+void USB_ClearInterrupts(USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt)
+{
+ USBx->GINTSTS |= interrupt;
+}
+
+/**
+ * @brief Returns USB core mode
+ * @param USBx Selected device
+ * @retval return core mode : Host or Device
+ * This parameter can be one of these values:
+ * 0 : Host
+ * 1 : Device
+ */
+uint32_t USB_GetMode(USB_OTG_GlobalTypeDef *USBx)
+{
+ return ((USBx->GINTSTS) & 0x1U);
+}
+
+/**
+ * @brief Activate EP0 for Setup transactions
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_ActivateSetup(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(USB_OTG_GlobalTypeDef *USBx, uint8_t dma, uint8_t *psetup)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t gSNPSiD = *(__IO 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 & (1U << 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)
+{
+ uint32_t count = 0U;
+
+ /* Wait for AHB master IDLE state. */
+ do
+ {
+ if (++count > 200000U)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
+
+ /* Core Soft Reset */
+ count = 0U;
+ USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
+
+ do
+ {
+ if (++count > 200000U)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_HostInit : Initializes the USB OTG controller registers
+ * for Host mode
+ * @param USBx Selected device
+ * @param cfg pointer to a USB_OTG_CfgTypeDef structure that contains
+ * the configuration information for the specified USBx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_HostInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
+{
+ uint32_t 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->CID & (0x1U << 8)) != 0U)
+ {
+ if (cfg.speed == USB_OTG_SPEED_FULL)
+ {
+ /* 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. */
+ (void)USB_FlushTxFifo(USBx, 0x10U); /* all Tx FIFOs */
+ (void)USB_FlushRxFifo(USBx);
+
+ /* Clear all pending HC Interrupts */
+ for (i = 0U; i < cfg.Host_channels; i++)
+ {
+ USBx_HC(i)->HCINT = 0xFFFFFFFFU;
+ USBx_HC(i)->HCINTMSK = 0U;
+ }
+
+ /* Enable VBUS driving */
+ (void)USB_DriveVbus(USBx, 1U);
+
+ HAL_Delay(200U);
+
+ /* Disable all interrupts. */
+ USBx->GINTMSK = 0U;
+
+ /* Clear any pending interrupts */
+ USBx->GINTSTS = 0xFFFFFFFFU;
+
+ if ((USBx->CID & (0x1U << 8)) != 0U)
+ {
+ /* set Rx FIFO size */
+ USBx->GRXFSIZ = 0x200U;
+ USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((0x100U << 16) & USB_OTG_NPTXFD) | 0x200U);
+ USBx->HPTXFSIZ = (uint32_t)(((0xE0U << 16) & USB_OTG_HPTXFSIZ_PTXFD) | 0x300U);
+ }
+ else
+ {
+ /* set Rx FIFO size */
+ USBx->GRXFSIZ = 0x80U;
+ USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((0x60U << 16) & USB_OTG_NPTXFD) | 0x80U);
+ USBx->HPTXFSIZ = (uint32_t)(((0x40U << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0xE0U);
+ }
+
+ /* 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 HAL_OK;
+}
+
+/**
+ * @brief USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the
+ * HCFG register on the PHY type and set the right frame interval
+ * @param USBx Selected device
+ * @param freq clock frequency
+ * This parameter can be one of these values:
+ * HCFG_48_MHZ : Full Speed 48 MHz Clock
+ * HCFG_6_MHZ : Low Speed 6 MHz Clock
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_InitFSLSPClkSel(USB_OTG_GlobalTypeDef *USBx, uint8_t freq)
+{
+ 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 = 48000U;
+ }
+ else if (freq == HCFG_6_MHZ)
+ {
+ USBx_HOST->HFIR = 6000U;
+ }
+ else
+ {
+ /* ... */
+ }
+
+ return HAL_OK;
+}
+
+/**
+* @brief USB_OTG_ResetPort : Reset Host Port
+ * @param USBx Selected device
+ * @retval HAL status
+ * @note (1)The application must wait at least 10 ms
+ * before clearing the reset bit.
+ */
+HAL_StatusTypeDef USB_ResetPort(USB_OTG_GlobalTypeDef *USBx)
+{
+ 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 : VBUS Active
+ * 1 : VBUS Inactive
+ * @retval HAL status
+*/
+HAL_StatusTypeDef USB_DriveVbus(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 Core speed
+ * @param USBx Selected device
+ * @retval speed : Host speed
+ * This parameter can be one of these values:
+ * @arg HCD_SPEED_HIGH: High speed mode
+ * @arg HCD_SPEED_FULL: Full speed mode
+ * @arg HCD_SPEED_LOW: Low speed mode
+ */
+uint32_t USB_GetHostSpeed(USB_OTG_GlobalTypeDef *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 *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ return (USBx_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
+}
+
+/**
+ * @brief Initialize a host channel
+ * @param USBx Selected device
+ * @param ch_num Channel number
+ * This parameter can be a value from 1 to 15
+ * @param epnum Endpoint number
+ * This parameter can be a value from 1 to 15
+ * @param dev_address Current device address
+ * This parameter can be a value from 0 to 255
+ * @param speed Current device speed
+ * This parameter can be one of these values:
+ * @arg USB_OTG_SPEED_HIGH: High speed mode
+ * @arg USB_OTG_SPEED_FULL: Full speed mode
+ * @arg USB_OTG_SPEED_LOW: Low speed mode
+ * @param ep_type Endpoint Type
+ * This parameter can be one of these values:
+ * @arg EP_TYPE_CTRL: Control type
+ * @arg EP_TYPE_ISOC: Isochronous type
+ * @arg EP_TYPE_BULK: Bulk type
+ * @arg EP_TYPE_INTR: Interrupt type
+ * @param mps Max Packet Size
+ * This parameter can be a value from 0 to32K
+ * @retval HAL state
+ */
+HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx,
+ uint8_t ch_num,
+ uint8_t epnum,
+ uint8_t dev_address,
+ uint8_t speed,
+ uint8_t ep_type,
+ uint16_t mps)
+{
+ HAL_StatusTypeDef ret = HAL_OK;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t HCcharEpDir, HCcharLowSpeed;
+
+ /* Clear old interrupt conditions for this host channel. */
+ USBx_HC((uint32_t)ch_num)->HCINT = 0xFFFFFFFFU;
+
+ /* 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
+ {
+ if ((USBx->CID & (0x1U << 8)) != 0U)
+ {
+ 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;
+ }
+
+ /* 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 = (0x1U << 15) & USB_OTG_HCCHAR_EPDIR;
+ }
+ else
+ {
+ HCcharEpDir = 0U;
+ }
+
+ if (speed == HPRT0_PRTSPD_LOW_SPEED)
+ {
+ HCcharLowSpeed = (0x1U << 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) | HCcharEpDir | HCcharLowSpeed;
+
+ if (ep_type == EP_TYPE_INTR)
+ {
+ 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;
+ static __IO uint32_t tmpreg = 0U;
+ uint8_t is_oddframe;
+ uint16_t len_words;
+ uint16_t num_packets;
+ uint16_t max_hc_pkt_count = 256U;
+
+ if (((USBx->CID & (0x1U << 8)) != 0U) && (hc->speed == USBH_HS_SPEED))
+ {
+ if ((dma == 0U) && (hc->do_ping == 1U))
+ {
+ (void)USB_DoPing(USBx, hc->ch_num);
+ return HAL_OK;
+ }
+ else if (dma == 1U)
+ {
+ USBx_HC(ch_num)->HCINTMSK &= ~(USB_OTG_HCINTMSK_NYET | USB_OTG_HCINTMSK_ACKM);
+ hc->do_ping = 0U;
+ }
+ 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->xfer_len = (uint32_t)num_packets * hc->max_packet;
+ }
+ }
+ else
+ {
+ num_packets = 1U;
+ }
+ if (hc->ep_is_in != 0U)
+ {
+ hc->xfer_len = (uint32_t)num_packets * hc->max_packet;
+ }
+
+ /* Initialize the HCTSIZn register */
+ USBx_HC(ch_num)->HCTSIZ = (hc->xfer_len & 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;
+
+ /* 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) /* Slave mode */
+ {
+ if ((hc->ep_is_in == 0U) && (hc->xfer_len > 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(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(USB_OTG_GlobalTypeDef *USBx, uint8_t hc_num)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t hcnum = (uint32_t)hc_num;
+ uint32_t count = 0U;
+ uint32_t HcEpType = (USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18;
+
+ /* 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->HNPTXSTS & (0xFFU << 16)) == 0U)
+ {
+ USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR;
+ do
+ {
+ 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_CHDIS;
+
+ if ((USBx_HOST->HPTXSTS & (0xFFU << 16)) == 0U)
+ {
+ USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR;
+ do
+ {
+ 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 Initiate Do Ping protocol
+ * @param USBx Selected device
+ * @param hc_num Host Channel number
+ * This parameter can be a value from 1 to 15
+ * @retval HAL state
+ */
+HAL_StatusTypeDef USB_DoPing(USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num)
+{
+ 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)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t count = 0U;
+ uint32_t value;
+ uint32_t i;
+
+ (void)USB_DisableGlobalInt(USBx);
+
+ /* Flush FIFO */
+ (void)USB_FlushTxFifo(USBx, 0x10U);
+ (void)USB_FlushRxFifo(USBx);
+
+ /* 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
+ {
+ 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 = 0xFFFFFFFFU;
+ USBx->GINTSTS = 0xFFFFFFFFU;
+
+ (void)USB_EnableGlobalInt(USBx);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_ActivateRemoteWakeup active remote wakeup signalling
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_ActivateRemoteWakeup(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(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) */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_ll_utils.c b/bsps/arm/stm32h7/hal/stm32h7xx_ll_utils.c
new file mode 100644
index 0000000000..cf19f61708
--- /dev/null
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_ll_utils.c
@@ -0,0 +1,975 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_utils.c
+ * @author MCD Application Team
+ * @brief UTILS LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_ll_utils.h"
+#include "stm32h7xx_ll_rcc.h"
+#include "stm32h7xx_ll_pwr.h"
+
+#ifdef USE_FULL_ASSERT
+ #include "stm32_assert.h"
+#else
+ #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+/** @addtogroup STM32H7xx_LL_Driver
+ * @{
+ */
+
+/** @addtogroup UTILS_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup UTILS_LL_Private_Constants
+ * @{
+ */
+#if (POWER_DOMAINS_NUMBER == 3U)
+#define UTILS_MAX_FREQUENCY_SCALE1 400000000U /*!< Maximum frequency for system clock at power scale1, in Hz */
+#define UTILS_MAX_FREQUENCY_SCALE2 300000000U /*!< Maximum frequency for system clock at power scale2, in Hz */
+#define UTILS_MAX_FREQUENCY_SCALE3 200000000U /*!< Maximum frequency for system clock at power scale3, in Hz */
+#else
+#define UTILS_MAX_FREQUENCY_SCALE0 280000000U /*!< Maximum frequency for system clock at power scale0, in Hz */
+#define UTILS_MAX_FREQUENCY_SCALE1 225000000U /*!< Maximum frequency for system clock at power scale1, in Hz */
+#define UTILS_MAX_FREQUENCY_SCALE2 160000000U /*!< Maximum frequency for system clock at power scale2, in Hz */
+#define UTILS_MAX_FREQUENCY_SCALE3 88000000U /*!< Maximum frequency for system clock at power scale3, in Hz */
+#endif /*POWER_DOMAINS_NUMBER == 3U*/
+
+/* Defines used for PLL range */
+#define UTILS_PLLVCO_INPUT_MIN1 1000000U /*!< Frequency min for the low range PLLVCO input, in Hz */
+#define UTILS_PLLVCO_INPUT_MAX1 2000000U /*!< Frequency max for the wide range PLLVCO input, in Hz */
+#define UTILS_PLLVCO_INPUT_MIN2 2000000U /*!< Frequency min for the low range PLLVCO input, in Hz */
+#define UTILS_PLLVCO_INPUT_MAX2 4000000U /*!< Frequency max for the wide range PLLVCO input, in Hz */
+#define UTILS_PLLVCO_INPUT_MIN3 4000000U /*!< Frequency min for the low range PLLVCO input, in Hz */
+#define UTILS_PLLVCO_INPUT_MAX3 8000000U /*!< Frequency max for the wide range PLLVCO input, in Hz */
+#define UTILS_PLLVCO_INPUT_MIN4 8000000U /*!< Frequency min for the low range PLLVCO input, in Hz */
+#define UTILS_PLLVCO_INPUT_MAX4 16000000U /*!< Frequency max for the wide range PLLVCO input, in Hz */
+
+#if (POWER_DOMAINS_NUMBER == 3U)
+#define UTILS_PLLVCO_MEDIUM_OUTPUT_MIN 150000000U /*!< Frequency min for the medium range PLLVCO output, in Hz */
+#define UTILS_PLLVCO_WIDE_OUTPUT_MIN 192000000U /*!< Frequency min for the wide range PLLVCO output, in Hz */
+#define UTILS_PLLVCO_MEDIUM_OUTPUT_MAX 420000000U /*!< Frequency max for the medium range PLLVCO output, in Hz */
+#define UTILS_PLLVCO_WIDE_OUTPUT_MAX 836000000U /*!< Frequency max for the wide range PLLVCO output, in Hz */
+#else
+#define UTILS_PLLVCO_MEDIUM_OUTPUT_MIN 150000000U /*!< Frequency min for the medium range PLLVCO output, in Hz */
+#define UTILS_PLLVCO_WIDE_OUTPUT_MIN 128000000U /*!< Frequency min for the wide range PLLVCO output, in Hz */
+#define UTILS_PLLVCO_MEDIUM_OUTPUT_MAX 420000000U /*!< Frequency max for the medium range PLLVCO output, in Hz */
+#define UTILS_PLLVCO_WIDE_OUTPUT_MAX 560000000U /*!< Frequency max for the wide range PLLVCO output, in Hz */
+#endif /*POWER_DOMAINS_NUMBER == 3U*/
+
+/* Defines used for HSE range */
+#define UTILS_HSE_FREQUENCY_MIN 4000000U /*!< Frequency min for HSE frequency, in Hz */
+#define UTILS_HSE_FREQUENCY_MAX 48000000U /*!< Frequency max for HSE frequency, in Hz */
+
+/* Defines used for FLASH latency according to HCLK Frequency */
+#if (POWER_DOMAINS_NUMBER == 2U)
+#define UTILS_SCALE0_LATENCY0_FREQ 44000000U /*!< HCLK frequency to set FLASH latency 0 in power scale 0 */
+#define UTILS_SCALE0_LATENCY1_FREQ 88000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 0 */
+#define UTILS_SCALE0_LATENCY2_FREQ 132000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 0 */
+#define UTILS_SCALE0_LATENCY3_FREQ 176000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 0 */
+#define UTILS_SCALE0_LATENCY4_FREQ 220000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 0 */
+#define UTILS_SCALE0_LATENCY5_FREQ 264000000U /*!< HCLK frequency to set FLASH latency 5 in power scale 0 */
+#define UTILS_SCALE0_LATENCY6_FREQ 280000000U /*!< HCLK frequency to set FLASH latency 6 in power scale 0 */
+
+#define UTILS_SCALE1_LATENCY0_FREQ 42000000U /*!< HCLK frequency to set FLASH latency 0 in power scale 1 */
+#define UTILS_SCALE1_LATENCY1_FREQ 84000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */
+#define UTILS_SCALE1_LATENCY2_FREQ 126000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */
+#define UTILS_SCALE1_LATENCY3_FREQ 168000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 1 */
+#define UTILS_SCALE1_LATENCY4_FREQ 210000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 1 */
+#define UTILS_SCALE1_LATENCY5_FREQ 225000000U /*!< HCLK frequency to set FLASH latency 5 in power scale 1 */
+
+#define UTILS_SCALE2_LATENCY0_FREQ 34000000U /*!< HCLK frequency to set FLASH latency 0 in power scale 2 */
+#define UTILS_SCALE2_LATENCY1_FREQ 68000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */
+#define UTILS_SCALE2_LATENCY2_FREQ 102000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */
+#define UTILS_SCALE2_LATENCY3_FREQ 136000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 2 */
+#define UTILS_SCALE2_LATENCY4_FREQ 160000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 2 */
+
+#define UTILS_SCALE3_LATENCY0_FREQ 22000000U /*!< HCLK frequency to set FLASH latency 0 in power scale 3 */
+#define UTILS_SCALE3_LATENCY1_FREQ 44000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 3 */
+#define UTILS_SCALE3_LATENCY2_FREQ 66000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 3 */
+#define UTILS_SCALE3_LATENCY3_FREQ 88000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 3 */
+
+#else
+
+#define UTILS_SCALE1_LATENCY0_FREQ 70000000U /*!< HCLK frequency to set FLASH latency 0 in power scale 1 */
+#define UTILS_SCALE1_LATENCY1_FREQ 140000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */
+#define UTILS_SCALE1_LATENCY2_FREQ 210000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */
+
+#define UTILS_SCALE2_LATENCY0_FREQ 55000000U /*!< HCLK frequency to set FLASH latency 0 in power scale 2 */
+#define UTILS_SCALE2_LATENCY1_FREQ 110000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */
+#define UTILS_SCALE2_LATENCY2_FREQ 165000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */
+#define UTILS_SCALE2_LATENCY3_FREQ 220000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 2 */
+
+#define UTILS_SCALE3_LATENCY0_FREQ 45000000U /*!< HCLK frequency to set FLASH latency 0 in power scale 3 */
+#define UTILS_SCALE3_LATENCY1_FREQ 90000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 3 */
+#define UTILS_SCALE3_LATENCY2_FREQ 135000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 3 */
+#define UTILS_SCALE3_LATENCY3_FREQ 180000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 3 */
+#define UTILS_SCALE3_LATENCY4_FREQ 225000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 3 */
+#endif /*POWER_DOMAINS_NUMBER == 2U*/
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup UTILS_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_UTILS_SYSCLK_DIV(__VALUE__) (((__VALUE__) == LL_RCC_SYSCLK_DIV_1) \
+ || ((__VALUE__) == LL_RCC_SYSCLK_DIV_2) \
+ || ((__VALUE__) == LL_RCC_SYSCLK_DIV_4) \
+ || ((__VALUE__) == LL_RCC_SYSCLK_DIV_8) \
+ || ((__VALUE__) == LL_RCC_SYSCLK_DIV_16) \
+ || ((__VALUE__) == LL_RCC_SYSCLK_DIV_64) \
+ || ((__VALUE__) == LL_RCC_SYSCLK_DIV_128) \
+ || ((__VALUE__) == LL_RCC_SYSCLK_DIV_256) \
+ || ((__VALUE__) == LL_RCC_SYSCLK_DIV_512))
+
+#define IS_LL_UTILS_AHB_DIV(__VALUE__) (((__VALUE__) == LL_RCC_AHB_DIV_1) \
+ || ((__VALUE__) == LL_RCC_AHB_DIV_2) \
+ || ((__VALUE__) == LL_RCC_AHB_DIV_4) \
+ || ((__VALUE__) == LL_RCC_AHB_DIV_8) \
+ || ((__VALUE__) == LL_RCC_AHB_DIV_16) \
+ || ((__VALUE__) == LL_RCC_AHB_DIV_64) \
+ || ((__VALUE__) == LL_RCC_AHB_DIV_128) \
+ || ((__VALUE__) == LL_RCC_AHB_DIV_256) \
+ || ((__VALUE__) == LL_RCC_AHB_DIV_512))
+
+#define IS_LL_UTILS_APB1_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB1_DIV_1) \
+ || ((__VALUE__) == LL_RCC_APB1_DIV_2) \
+ || ((__VALUE__) == LL_RCC_APB1_DIV_4) \
+ || ((__VALUE__) == LL_RCC_APB1_DIV_8) \
+ || ((__VALUE__) == LL_RCC_APB1_DIV_16))
+
+#define IS_LL_UTILS_APB2_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB2_DIV_1) \
+ || ((__VALUE__) == LL_RCC_APB2_DIV_2) \
+ || ((__VALUE__) == LL_RCC_APB2_DIV_4) \
+ || ((__VALUE__) == LL_RCC_APB2_DIV_8) \
+ || ((__VALUE__) == LL_RCC_APB2_DIV_16))
+
+#define IS_LL_UTILS_APB3_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB3_DIV_1) \
+ || ((__VALUE__) == LL_RCC_APB3_DIV_2) \
+ || ((__VALUE__) == LL_RCC_APB3_DIV_4) \
+ || ((__VALUE__) == LL_RCC_APB3_DIV_8) \
+ || ((__VALUE__) == LL_RCC_APB3_DIV_16))
+
+#define IS_LL_UTILS_APB4_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB4_DIV_1) \
+ || ((__VALUE__) == LL_RCC_APB4_DIV_2) \
+ || ((__VALUE__) == LL_RCC_APB4_DIV_4) \
+ || ((__VALUE__) == LL_RCC_APB4_DIV_8) \
+ || ((__VALUE__) == LL_RCC_APB4_DIV_16))
+
+#define IS_LL_UTILS_PLLM_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 63U))
+
+#if (POWER_DOMAINS_NUMBER == 3U)
+#define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((4U <= (__VALUE__)) && ((__VALUE__) <= 512U))
+#else
+#define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((8U <= (__VALUE__)) && ((__VALUE__) <= 420U))
+#endif /*POWER_DOMAINS_NUMBER == 3U*/
+
+#define IS_LL_UTILS_PLLP_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 128U))
+
+#define IS_LL_UTILS_FRACN_VALUE(__VALUE__) ((__VALUE__) <= 0x1FFFU)
+
+#define IS_LL_UTILS_PLLVCO_INPUT(__VALUE__, __RANGE__) ( \
+(((__RANGE__) == LL_RCC_PLLINPUTRANGE_1_2) && (UTILS_PLLVCO_INPUT_MIN1 <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX1)) || \
+(((__RANGE__) == LL_RCC_PLLINPUTRANGE_2_4) && (UTILS_PLLVCO_INPUT_MIN2 <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX2)) || \
+(((__RANGE__) == LL_RCC_PLLINPUTRANGE_4_8) && (UTILS_PLLVCO_INPUT_MIN3 <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX3)) || \
+(((__RANGE__) == LL_RCC_PLLINPUTRANGE_8_16) && (UTILS_PLLVCO_INPUT_MIN4 <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX4)))
+
+#define IS_LL_UTILS_PLLVCO_OUTPUT(__VALUE__, __RANGE__) ( \
+(((__RANGE__) == LL_RCC_PLLVCORANGE_MEDIUM) && (UTILS_PLLVCO_MEDIUM_OUTPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_MEDIUM_OUTPUT_MAX)) || \
+(((__RANGE__) == LL_RCC_PLLVCORANGE_WIDE) && (UTILS_PLLVCO_WIDE_OUTPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_WIDE_OUTPUT_MAX)))
+
+#define IS_LL_UTILS_CHECK_VCO_RANGES(__RANGEIN__, __RANGEOUT__) ( \
+(((__RANGEIN__) == LL_RCC_PLLINPUTRANGE_1_2) && ((__RANGEOUT__) == LL_RCC_PLLVCORANGE_MEDIUM)) || \
+(((__RANGEIN__) != LL_RCC_PLLINPUTRANGE_1_2) && ((__RANGEOUT__) == LL_RCC_PLLVCORANGE_WIDE)))
+
+#if (POWER_DOMAINS_NUMBER == 3U)
+#define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1) : \
+ (LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE2) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2) : \
+ ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE3))
+#else
+#define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE0) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE0) : \
+ (LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1) : \
+ (LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE2) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2) : \
+ ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE3))
+#endif /*POWER_DOMAINS_NUMBER == 3U*/
+
+#define IS_LL_UTILS_HSE_BYPASS(__STATE__) (((__STATE__) == LL_UTILS_HSEBYPASS_ON) \
+ || ((__STATE__) == LL_UTILS_HSEBYPASS_OFF))
+
+#define IS_LL_UTILS_HSE_FREQUENCY(__FREQUENCY__) (((__FREQUENCY__) >= UTILS_HSE_FREQUENCY_MIN) && ((__FREQUENCY__) <= UTILS_HSE_FREQUENCY_MAX))
+/**
+ * @}
+ */
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup UTILS_LL_Private_Functions UTILS Private functions
+ * @{
+ */
+static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct);
+static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct);
+static ErrorStatus UTILS_IsPLLsReady(void);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup UTILS_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup UTILS_LL_EF_DELAY
+ * @{
+ */
+#if defined (DUAL_CORE)
+/**
+ * @brief This function configures the Cortex-M SysTick source to have 1ms time base.
+ * @note When a RTOS is used, it is recommended to avoid changing the Systick
+ * configuration by calling this function, for a delay use rather osDelay RTOS service.
+ * @param CPU_Frequency Core frequency in Hz
+ * @note CPU_Frequency can be calculated thanks to RCC helper macro or function
+ * @ref LL_RCC_GetSystemClocksFreq
+ * LL_RCC_GetSystemClocksFreq() is used to calculate the CM7 clock frequency
+ * and __LL_RCC_CALC_HCLK_FREQ is used to caluclate the CM4 clock frequency.
+ * @retval None
+ */
+#else
+/**
+ * @brief This function configures the Cortex-M SysTick source to have 1ms time base.
+ * @note When a RTOS is used, it is recommended to avoid changing the Systick
+ * configuration by calling this function, for a delay use rather osDelay RTOS service.
+ * @param CPU_Frequency Core frequency in Hz
+ * @note CPU_Frequency can be calculated thanks to RCC helper macro or function
+ * @ref LL_RCC_GetSystemClocksFreq
+ * @retval None
+ */
+#endif /* DUAL_CORE */
+void LL_Init1msTick(uint32_t CPU_Frequency)
+{
+ /* Use frequency provided in argument */
+ LL_InitTick(CPU_Frequency, 1000U);
+}
+
+
+/**
+ * @brief This function provides accurate delay (in milliseconds) based
+ * on SysTick counter flag
+ * @note When a RTOS is used, it is recommended to avoid using blocking delay
+ * and use rather osDelay service.
+ * @note To respect 1ms timebase, user should call @ref LL_Init1msTick function which
+ * will configure Systick to 1ms
+ * @param Delay specifies the delay time length, in milliseconds.
+ * @retval None
+ */
+void LL_mDelay(uint32_t Delay)
+{
+ uint32_t count = Delay;
+ __IO uint32_t tmp = SysTick->CTRL; /* Clear the COUNTFLAG first */
+ /* Add this code to indicate that local variable is not used */
+ ((void)tmp);
+
+ /* Add a period to guaranty minimum wait */
+ if(count < LL_MAX_DELAY)
+ {
+ count++;
+ }
+
+ while (count != 0U)
+ {
+ if((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)
+ {
+ count--;
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup UTILS_EF_SYSTEM
+ * @brief System Configuration functions
+ *
+ @verbatim
+ ===============================================================================
+ ##### System Configuration functions #####
+ ===============================================================================
+ [..]
+ System, AHB and APB buses clocks configuration
+
+#if (POWER_DOMAINS_NUMBER == 3U)
+ (+) The maximum frequency of the SYSCLK is 400 MHz and HCLK is 200 MHz.
+ (+) The maximum frequency of the PCLK1, PCLK2, PCLK3 and PCLK4 is 100 MHz.
+ @endverbatim
+ @internal
+ Depending on the device voltage range, the maximum frequency should be
+ adapted accordingly:
+ (++) +----------------------------------------------------------------------------+
+ (++) | Wait states | HCLK clock frequency (MHz) |
+ (++) | |-----------------------------------------------------------|
+ (++) | (Latency) | voltage range 1 | voltage range 2 | voltage range 3 |
+ (++) | | 1.15V - 1.26V | 1.05V - 1.15V | 0.95V - 1.05V |
+ (++) |----------------|-------------------|-------------------|-------------------|
+ (++) |0WS(1CPU cycle) | 0 < HCLK <= 70 | 0 < HCLK <= 55 | 0 < HCLK <= 45 |
+ (++) |----------------|-------------------|-------------------|-------------------|
+ (++) |1WS(2CPU cycle) | 70 < HCLK <= 140 | 55 < HCLK <= 110 | 45 < HCLK <= 90 |
+ (++) |----------------|-------------------|-------------------|-------------------|
+ (++) |2WS(3CPU cycle) | 140 < HCLK <= 210 | 110 < HCLK <= 165 | 90 < HCLK <= 135 |
+ (++) |----------------|-------------------|-------------------|-------------------|
+ (++) |3WS(4CPU cycle) | -- | 165 < HCLK <= 220 | 135 < HCLK <= 180 |
+ (++) |----------------|-------------------|-------------------|-------------------|
+ (++) |4WS(5CPU cycle) | -- | -- | 180 < HCLK <= 225 |
+ (++) +----------------------------------------------------------------------------+
+
+#else
+ (+) The maximum frequency of the SYSCLK is 280 MHz and HCLK is 280 MHz.
+ (+) The maximum frequency of the PCLK1, PCLK2, PCLK3 and PCLK4 is 140 MHz.
+ @endverbatim
+ @internal
+ Depending on the device voltage range, the maximum frequency should be
+ adapted accordingly:
+ (++) +------------------------------------------------------------------------------------------------+
+ (++) | Wait states | HCLK clock frequency (MHz) |
+ (++) | |-------------------------------------------------------------------------------|
+ (++) | (Latency) | voltage range 0 | voltage range 1 | voltage range 2 | voltage range 3 |
+ (++) | | 1.26V - 1.35V | 1.15V - 1.26V | 1.05V - 1.15V | 0.95V - 1.05V |
+ (++) |----------------|-------------------|-------------------|-------------------|-------------------|
+ (++) |0WS(1CPU cycle) | 0 < HCLK <= 44 | 0 < HCLK <= 42 | 0 < HCLK <= 34 | 0 < HCLK <= 22 |
+ (++) |----------------|-------------------|-------------------|-------------------|-------------------|
+ (++) |1WS(2CPU cycle) | 44 < HCLK <= 88 | 42 < HCLK <= 84 | 34 < HCLK <= 68 | 22 < HCLK <= 44 |
+ (++) |----------------|-------------------|-------------------|-------------------|-------------------|
+ (++) |2WS(3CPU cycle) | 88 < HCLK <= 132 | 84 < HCLK <= 126 | 68 < HCLK <= 102 | 44 < HCLK <= 66 |
+ (++) |----------------|-------------------|-------------------|-------------------|-------------------|
+ (++) |3WS(4CPU cycle) | 132 < HCLK <= 176 | 126 < HCLK <= 168 | 102 < HCLK <= 136 | 66 < HCLK <= 88 |
+ (++) |----------------|-------------------|-------------------|-------------------|-------------------|
+ (++) |4WS(5CPU cycle) | 176 < HCLK <= 220 | 168 < HCLK <= 210 | 136 < HCLK <= 160 | -- |
+ (++) +------------------------------------------------------------------------------------------------+
+ (++) |5WS(6CPU cycle) | 220 < HCLK <= 264 | 210 < HCLK <= 225 | -- | -- |
+ (++) +------------------------------------------------------------------------------------------------+
+ (++) |6WS(7CPU cycle) | 264 < HCLK <= 280 | -- | -- | -- |
+ (++) +------------------------------------------------------------------------------------------------+
+ (++) |7WS(8CPU cycle) | -- | -- | -- | -- |
+ (++) +------------------------------------------------------------------------------------------------+
+
+#endif
+ @endinternal
+ * @{
+ */
+#if defined (DUAL_CORE)
+/**
+ * @brief This function sets directly SystemCoreClock CMSIS variable.
+ * @note Variable can be calculated also through SystemCoreClockUpdate function.
+ * @param CPU_Frequency Core frequency in Hz
+ * @note CPU_Frequency can be calculated thanks to RCC helper macro or function
+ * @ref LL_RCC_GetSystemClocksFreq
+ * LL_RCC_GetSystemClocksFreq() is used to calculate the CM7 clock frequency
+ * and __LL_RCC_CALC_HCLK_FREQ is used to caluclate the CM4 clock frequency.
+ * @retval None
+ */
+#else
+/**
+ * @brief This function sets directly SystemCoreClock CMSIS variable.
+ * @note Variable can be calculated also through SystemCoreClockUpdate function.
+ * @param CPU_Frequency Core frequency in Hz
+ * @note CPU_Frequency can be calculated thanks to RCC helper macro or function
+ * @ref LL_RCC_GetSystemClocksFreq
+ * @retval None
+ */
+#endif /* DUAL_CORE */
+void LL_SetSystemCoreClock(uint32_t CPU_Frequency)
+{
+ /* HCLK clock frequency */
+ SystemCoreClock = CPU_Frequency;
+}
+
+/**
+ * @brief This function configures system clock at maximum frequency with HSI as clock source of the PLL
+ * @note The application need to ensure that PLL is disabled.
+ * @note Function is based on the following formula:
+ * - PLL output frequency = (((HSI frequency / PLLM) * PLLN) / PLLP)
+ * - PLLM: ensure that the VCO input frequency ranges from 1 to 16 MHz (PLLVCO_input = HSI frequency / PLLM)
+ * - PLLN: ensure that the VCO output frequency is between 150 and 836 MHz or 128 to 560 MHz(*) (PLLVCO_output = PLLVCO_input * PLLN)
+ * - PLLP: ensure that max frequency at 400000000 Hz or 280000000 Hz is reach (PLLVCO_output / PLLP)
+ * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
+ * the configuration information for the PLL.
+ * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
+ * the configuration information for the BUS prescalers.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: Max frequency configuration done
+ * - ERROR: Max frequency configuration not done
+ *
+ * (*) : For stm32h7a3xx, stm32h7b3xx and stm32h7b0xx family lines.
+ *
+ */
+ErrorStatus LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
+ LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
+{
+ ErrorStatus status;
+#ifdef USE_FULL_ASSERT
+ uint32_t vcoinput_freq, vcooutput_freq;
+#endif
+ uint32_t pllfreq, hsi_clk;
+
+ /* Check the parameters */
+ assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLInitStruct->PLLM));
+ assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLInitStruct->PLLN));
+ assert_param(IS_LL_UTILS_PLLP_VALUE(UTILS_PLLInitStruct->PLLP));
+ assert_param(IS_LL_UTILS_FRACN_VALUE(UTILS_PLLInitStruct->FRACN));
+
+ hsi_clk = (HSI_VALUE >> (LL_RCC_HSI_GetDivider() >> RCC_CR_HSIDIV_Pos));
+
+ /* Check VCO Input frequency */
+#ifdef USE_FULL_ASSERT
+ vcoinput_freq = hsi_clk / UTILS_PLLInitStruct->PLLM;
+#endif
+ assert_param(IS_LL_UTILS_PLLVCO_INPUT(vcoinput_freq, UTILS_PLLInitStruct->VCO_Input));
+
+ /* Check VCO Output frequency */
+#ifdef USE_FULL_ASSERT
+ vcooutput_freq = LL_RCC_CalcPLLClockFreq(hsi_clk, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN, UTILS_PLLInitStruct->FRACN, 1UL);
+#endif
+ assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(vcooutput_freq, UTILS_PLLInitStruct->VCO_Output));
+
+ /* Check VCO Input ranges */
+ assert_param(IS_LL_UTILS_CHECK_VCO_RANGES(UTILS_PLLInitStruct->VCO_Input, UTILS_PLLInitStruct->VCO_Output));
+
+ /* Check if one of the PLL is enabled */
+ if(UTILS_IsPLLsReady() == SUCCESS)
+ {
+ /* Calculate the new PLL output frequency */
+ pllfreq = UTILS_GetPLLOutputFrequency(hsi_clk, UTILS_PLLInitStruct);
+
+ /* Enable HSI if not enabled */
+ if(LL_RCC_HSI_IsReady() != 1U)
+ {
+ LL_RCC_HSI_Enable();
+ while (LL_RCC_HSI_IsReady() != 1U)
+ {
+ /* Wait for HSI ready */
+ }
+ }
+
+ /* Configure PLL */
+ LL_RCC_PLL1P_Enable();
+ LL_RCC_PLL1FRACN_Enable();
+ LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI);
+ LL_RCC_PLL1_SetVCOInputRange(UTILS_PLLInitStruct->VCO_Input);
+ LL_RCC_PLL1_SetVCOOutputRange(UTILS_PLLInitStruct->VCO_Output);
+ LL_RCC_PLL1_SetM(UTILS_PLLInitStruct->PLLM);
+ LL_RCC_PLL1_SetN(UTILS_PLLInitStruct->PLLN);
+ LL_RCC_PLL1_SetP(UTILS_PLLInitStruct->PLLP);
+ LL_RCC_PLL1_SetFRACN(UTILS_PLLInitStruct->FRACN);
+
+ /* Enable PLL and switch system clock to PLL */
+ status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
+ }
+ else
+ {
+ /* Current PLL configuration cannot be modified */
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief This function configures system clock with HSE as clock source of the PLL
+ * @note The application need to ensure that PLL is disabled.
+ * @note Function is based on the following formula:
+ * - PLL output frequency = (((HSE frequency / PLLM) * PLLN) / PLLP)
+ * - PLLM: ensure that the VCO input frequency ranges from 0.95 to 2.10 MHz (PLLVCO_input = HSE frequency / PLLM)
+ * - PLLN: ensure that the VCO output frequency is between 150 and 836 MHz or 128 to 560 MHz(*) (PLLVCO_output = PLLVCO_input * PLLN)
+ * - PLLP: ensure that max frequency at 400000000 Hz or 280000000 Hz(*) is reached (PLLVCO_output / PLLP)
+ * @param HSEFrequency Value between Min_Data = 4000000 and Max_Data = 48000000
+ * @param HSEBypass This parameter can be one of the following values:
+ * @arg @ref LL_UTILS_HSEBYPASS_ON
+ * @arg @ref LL_UTILS_HSEBYPASS_OFF
+ * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
+ * the configuration information for the PLL.
+ * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
+ * the configuration information for the BUS prescalers.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: Max frequency configuration done
+ * - ERROR: Max frequency configuration not done
+ *
+ * (*) : For stm32h7a3xx, stm32h7b3xx and stm32h7b0xx family lines.
+ *
+ */
+ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEFrequency, uint32_t HSEBypass,
+ LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
+{
+ ErrorStatus status;
+#ifdef USE_FULL_ASSERT
+ uint32_t vcoinput_freq, vcooutput_freq;
+#endif
+ uint32_t pllfreq;
+
+ /* Check the parameters */
+ assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLInitStruct->PLLM));
+ assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLInitStruct->PLLN));
+ assert_param(IS_LL_UTILS_PLLP_VALUE(UTILS_PLLInitStruct->PLLP));
+ assert_param(IS_LL_UTILS_FRACN_VALUE(UTILS_PLLInitStruct->FRACN));
+ assert_param(IS_LL_UTILS_HSE_FREQUENCY(HSEFrequency));
+ assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass));
+
+ /* Check VCO Input frequency */
+#ifdef USE_FULL_ASSERT
+ vcoinput_freq = HSEFrequency / UTILS_PLLInitStruct->PLLM;
+#endif
+ assert_param(IS_LL_UTILS_PLLVCO_INPUT(vcoinput_freq, UTILS_PLLInitStruct->VCO_Input));
+
+ /* Check VCO output frequency */
+#ifdef USE_FULL_ASSERT
+ vcooutput_freq = LL_RCC_CalcPLLClockFreq(HSEFrequency, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN, UTILS_PLLInitStruct->FRACN, 1U);
+#endif
+ assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(vcooutput_freq, UTILS_PLLInitStruct->VCO_Output));
+
+ /* Check VCO Input/output ranges compatibility */
+ assert_param(IS_LL_UTILS_CHECK_VCO_RANGES(UTILS_PLLInitStruct->VCO_Input, UTILS_PLLInitStruct->VCO_Output));
+
+ /* Check if one of the PLL is enabled */
+ if(UTILS_IsPLLsReady() == SUCCESS)
+ {
+ /* Calculate the new PLL output frequency */
+ pllfreq = UTILS_GetPLLOutputFrequency(HSEFrequency, UTILS_PLLInitStruct);
+
+ /* Enable HSE if not enabled */
+ if(LL_RCC_HSE_IsReady() != 1U)
+ {
+ /* Check if need to enable HSE bypass feature or not */
+ if(HSEBypass == LL_UTILS_HSEBYPASS_ON)
+ {
+ LL_RCC_HSE_EnableBypass();
+ }
+ else
+ {
+ LL_RCC_HSE_DisableBypass();
+ }
+
+ /* Enable HSE */
+ LL_RCC_HSE_Enable();
+ while (LL_RCC_HSE_IsReady() != 1U)
+ {
+ /* Wait for HSE ready */
+ }
+ }
+
+ /* Configure PLL */
+ LL_RCC_PLL1P_Enable();
+ LL_RCC_PLL1FRACN_Enable();
+ LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE);
+ LL_RCC_PLL1_SetVCOInputRange(UTILS_PLLInitStruct->VCO_Input);
+ LL_RCC_PLL1_SetVCOOutputRange(UTILS_PLLInitStruct->VCO_Output);
+ LL_RCC_PLL1_SetM(UTILS_PLLInitStruct->PLLM);
+ LL_RCC_PLL1_SetN(UTILS_PLLInitStruct->PLLN);
+ LL_RCC_PLL1_SetP(UTILS_PLLInitStruct->PLLP);
+ LL_RCC_PLL1_SetFRACN(UTILS_PLLInitStruct->FRACN);
+
+ /* Enable PLL and switch system clock to PLL */
+ status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
+ }
+ else
+ {
+ /* Current PLL configuration cannot be modified */
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Update number of Flash wait states in line with new frequency and current
+ voltage range.
+ * @param HCLK_Frequency HCLK frequency
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: Latency has been modified
+ * - ERROR: Latency cannot be modified
+ */
+ErrorStatus LL_SetFlashLatency(uint32_t HCLK_Frequency)
+{
+ ErrorStatus status = SUCCESS;
+ uint32_t timeout;
+ uint32_t getlatency;
+ uint32_t latency = LL_FLASH_LATENCY_0; /* default value 0WS */
+
+
+
+ /* Frequency cannot be equal to 0 */
+ if (HCLK_Frequency == 0U)
+ {
+ status = ERROR;
+ }
+ else
+ {
+#if (POWER_DOMAINS_NUMBER == 2U)
+ if(LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE0)
+ {
+ if((HCLK_Frequency > UTILS_SCALE0_LATENCY5_FREQ) && (HCLK_Frequency <= UTILS_SCALE0_LATENCY6_FREQ))
+ {
+ /* 264 < HCLK <= 280 => 6WS (7 CPU cycles) */
+ latency = LL_FLASH_LATENCY_6;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE0_LATENCY4_FREQ) && (HCLK_Frequency <= UTILS_SCALE0_LATENCY5_FREQ))
+ {
+ /* 220 < HCLK <= 264 => 5WS (6 CPU cycles) */
+ latency = LL_FLASH_LATENCY_5;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE0_LATENCY3_FREQ) && (HCLK_Frequency <= UTILS_SCALE0_LATENCY4_FREQ))
+ {
+ /* 176 < HCLK <= 220 => 4WS (5 CPU cycles) */
+ latency = LL_FLASH_LATENCY_4;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE0_LATENCY2_FREQ) && (HCLK_Frequency <= UTILS_SCALE0_LATENCY3_FREQ))
+ {
+ /* 132 < HCLK <= 176 => 3WS (4 CPU cycles) */
+ latency = LL_FLASH_LATENCY_3;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE0_LATENCY1_FREQ) && (HCLK_Frequency <= UTILS_SCALE0_LATENCY2_FREQ))
+ {
+ /* 88 < HCLK <= 132 => 2WS (3 CPU cycles) */
+ latency = LL_FLASH_LATENCY_2;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE0_LATENCY0_FREQ) && (HCLK_Frequency <= UTILS_SCALE0_LATENCY1_FREQ))
+ {
+ /* 44 < HCLK <= 88 => 1WS (2 CPU cycles) */
+ latency = LL_FLASH_LATENCY_1;
+ }
+ else if(HCLK_Frequency <= UTILS_SCALE0_LATENCY0_FREQ)
+ {
+ /* HCLK <= 44 => 0WS (1 CPU cycles) : Do nothing keep latency to default LL_FLASH_LATENCY_0 */
+ }
+ else
+ {
+ status = ERROR;
+ }
+ }
+ else if(LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1)
+ {
+ if((HCLK_Frequency > UTILS_SCALE1_LATENCY4_FREQ) && (HCLK_Frequency <= UTILS_SCALE1_LATENCY5_FREQ))
+ {
+ /* 210 < HCLK <= 225 => 5WS (6 CPU cycles) */
+ latency = LL_FLASH_LATENCY_5;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE1_LATENCY3_FREQ) && (HCLK_Frequency <= UTILS_SCALE1_LATENCY4_FREQ))
+ {
+ /* 168 < HCLK <= 210 => 4WS (5 CPU cycles) */
+ latency = LL_FLASH_LATENCY_4;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE1_LATENCY2_FREQ) && (HCLK_Frequency <= UTILS_SCALE1_LATENCY3_FREQ))
+ {
+ /* 126 < HCLK <= 168 => 3WS (4 CPU cycles) */
+ latency = LL_FLASH_LATENCY_3;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE1_LATENCY1_FREQ) && (HCLK_Frequency <= UTILS_SCALE1_LATENCY2_FREQ))
+#else
+ if(LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1)
+ {
+ if((HCLK_Frequency > UTILS_SCALE1_LATENCY1_FREQ) && (HCLK_Frequency <= UTILS_SCALE1_LATENCY2_FREQ))
+#endif /*POWER_DOMAINS_NUMBER == 2U*/
+ {
+ /* 140 < HCLK <= 210 => 2WS (3 CPU cycles) */
+ latency = LL_FLASH_LATENCY_2;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE1_LATENCY0_FREQ) && (HCLK_Frequency <= UTILS_SCALE1_LATENCY1_FREQ))
+ {
+ /* 70 < HCLK <= 140 => 1WS (2 CPU cycles) */
+ latency = LL_FLASH_LATENCY_1;
+ }
+ else if(HCLK_Frequency <= UTILS_SCALE1_LATENCY0_FREQ)
+ {
+ /* HCLK <= 70 => 0WS (1 CPU cycles) : Do nothing keep latency to default LL_FLASH_LATENCY_0 */
+ }
+ else
+ {
+ status = ERROR;
+ }
+ }
+ else if(LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE2)
+ {
+#if (POWER_DOMAINS_NUMBER == 2U)
+ if((HCLK_Frequency > UTILS_SCALE2_LATENCY3_FREQ) && (HCLK_Frequency <= UTILS_SCALE2_LATENCY4_FREQ))
+ {
+ /* 136 < HCLK <= 160 => 4WS (5 CPU cycles) */
+ latency = LL_FLASH_LATENCY_4;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE2_LATENCY2_FREQ) && (HCLK_Frequency <= UTILS_SCALE2_LATENCY3_FREQ))
+#else
+ if((HCLK_Frequency > UTILS_SCALE2_LATENCY2_FREQ) && (HCLK_Frequency <= UTILS_SCALE2_LATENCY3_FREQ))
+#endif /*POWER_DOMAINS_NUMBER == 2U*/
+ {
+ /* 165 < HCLK <= 220 => 3WS (4 CPU cycles) */
+ latency = LL_FLASH_LATENCY_3;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE2_LATENCY1_FREQ) && (HCLK_Frequency <= UTILS_SCALE2_LATENCY2_FREQ))
+ {
+ /* 110 < HCLK <= 165 => 2WS (3 CPU cycles) */
+ latency = LL_FLASH_LATENCY_2;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE2_LATENCY0_FREQ) && (HCLK_Frequency <= UTILS_SCALE2_LATENCY1_FREQ))
+ {
+ /* 55 < HCLK <= 110 => 1WS (2 CPU cycles) */
+ latency = LL_FLASH_LATENCY_1;
+ }
+ else if(HCLK_Frequency <= UTILS_SCALE2_LATENCY0_FREQ)
+ {
+ /* HCLK <= 55 => 0WS (1 CPU cycles) : Do nothing keep latency to default LL_FLASH_LATENCY_0 */
+ }
+ else
+ {
+ status = ERROR;
+ }
+ }
+ else /* Scale 3 */
+ {
+#if (POWER_DOMAINS_NUMBER == 3U)
+ if((HCLK_Frequency > UTILS_SCALE3_LATENCY3_FREQ) && (HCLK_Frequency <= UTILS_SCALE3_LATENCY4_FREQ))
+ {
+ /* 180 < HCLK <= 225 => 4WS (5 CPU cycles) */
+ latency = LL_FLASH_LATENCY_4;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE3_LATENCY2_FREQ) && (HCLK_Frequency <= UTILS_SCALE3_LATENCY3_FREQ))
+#else
+ if((HCLK_Frequency > UTILS_SCALE3_LATENCY2_FREQ) && (HCLK_Frequency <= UTILS_SCALE3_LATENCY3_FREQ))
+#endif /*POWER_DOMAINS_NUMBER == 3U*/
+ {
+ /* 135 < HCLK <= 180 => 3WS (4 CPU cycles) */
+ latency = LL_FLASH_LATENCY_3;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE3_LATENCY1_FREQ) && (HCLK_Frequency <= UTILS_SCALE3_LATENCY2_FREQ))
+ {
+ /* 90 < HCLK <= 135 => 2WS (3 CPU cycles) */
+ latency = LL_FLASH_LATENCY_2;
+ }
+ else if((HCLK_Frequency > UTILS_SCALE3_LATENCY0_FREQ) && (HCLK_Frequency <= UTILS_SCALE3_LATENCY1_FREQ))
+ {
+ /* 45 < HCLK <= 90 => 1WS (2 CPU cycles) */
+ latency = LL_FLASH_LATENCY_1;
+ }
+ else if(HCLK_Frequency <= UTILS_SCALE3_LATENCY0_FREQ)
+ {
+ /* HCLK <= 45 => 0WS (1 CPU cycles) : Do nothing keep latency to default LL_FLASH_LATENCY_0 */
+ }
+ else
+ {
+ status = ERROR;
+ }
+ }
+
+ if(status == SUCCESS)
+ {
+ LL_FLASH_SetLatency(latency);
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ timeout = 2;
+ do
+ {
+ /* Wait for Flash latency to be updated */
+ getlatency = LL_FLASH_GetLatency();
+ timeout--;
+ } while ((getlatency != latency) && (timeout > 0U));
+
+ if(getlatency != latency)
+ {
+ status = ERROR;
+ }
+ }
+
+ }
+
+ return status;
+}
+
+
+/**
+ * @}
+ */
+
+/** @addtogroup UTILS_LL_Private_Functions
+ * @{
+ */
+
+
+/**
+ * @brief Function to check that PLL can be modified
+ * @param PLL_InputFrequency PLL input frequency (in Hz)
+ * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
+ * the configuration information for the PLL.
+ * @retval PLL output frequency (in Hz)
+ */
+static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct)
+{
+ uint32_t pllfreq;
+
+ /* Check the parameters */
+ assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLInitStruct->PLLM));
+ assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLInitStruct->PLLN));
+ assert_param(IS_LL_UTILS_PLLP_VALUE(UTILS_PLLInitStruct->PLLP));
+ assert_param(IS_LL_UTILS_FRACN_VALUE(UTILS_PLLInitStruct->FRACN));
+
+ pllfreq = LL_RCC_CalcPLLClockFreq(PLL_InputFrequency, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN, UTILS_PLLInitStruct->FRACN, UTILS_PLLInitStruct->PLLP);
+
+ return pllfreq;
+}
+
+/**
+ * @brief Check that all PLLs are ready therefore configuration can be done
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: All PLLs are ready so configuration can be done
+ * - ERROR: One PLL at least is busy
+ */
+static ErrorStatus UTILS_IsPLLsReady(void)
+{
+ ErrorStatus status = SUCCESS;
+
+ /* Check if one of the PLL1 is busy */
+ if(LL_RCC_PLL1_IsReady() != 0U)
+ {
+ /* PLL1 configuration cannot be done */
+ status = ERROR;
+ }
+
+ /* Check if one of the PLL2 is busy */
+ if(LL_RCC_PLL2_IsReady() != 0U)
+ {
+ /* PLL2 configuration cannot be done */
+ status = ERROR;
+ }
+
+ /* Check if one of the PLL3 is busy */
+ if(LL_RCC_PLL3_IsReady() != 0U)
+ {
+ /* PLL3 configuration cannot be done */
+ status = ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Function to enable PLL and switch system clock to PLL
+ * @param SYSCLK_Frequency SYSCLK frequency
+ * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
+ * the configuration information for the BUS prescalers.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: No problem to switch system to PLL
+ * - ERROR: Problem to switch system to PLL
+ */
+static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
+{
+ ErrorStatus status = SUCCESS;
+ uint32_t new_hclk_frequency;
+
+ assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->SYSCLKDivider));
+ assert_param(IS_LL_UTILS_AHB_DIV(UTILS_ClkInitStruct->AHBCLKDivider));
+ assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider));
+ assert_param(IS_LL_UTILS_APB2_DIV(UTILS_ClkInitStruct->APB2CLKDivider));
+ assert_param(IS_LL_UTILS_APB3_DIV(UTILS_ClkInitStruct->APB3CLKDivider));
+ assert_param(IS_LL_UTILS_APB4_DIV(UTILS_ClkInitStruct->APB4CLKDivider));
+
+ /* Calculate the new HCLK frequency */
+ new_hclk_frequency = LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->AHBCLKDivider);
+
+ /* Increasing the number of wait states because of higher CPU frequency */
+ if (SystemD2Clock < new_hclk_frequency)
+ {
+ /* Set FLASH latency to highest latency */
+ status = LL_SetFlashLatency(new_hclk_frequency);
+ }
+
+ /* Update system clock configuration */
+ if(status == SUCCESS)
+ {
+ /* Enable PLL */
+ LL_RCC_PLL1_Enable();
+ while (LL_RCC_PLL1_IsReady() != 1U)
+ {
+ /* Wait for PLL ready */
+ }
+
+ /* Set All APBxPrescaler to the Highest Divider */
+ LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_16);
+ LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_16);
+ LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_16);
+ LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_16);
+
+ /* Set SYS prescaler*/
+ LL_RCC_SetSysPrescaler(UTILS_ClkInitStruct->SYSCLKDivider);
+
+ /* Set AHB prescaler*/
+ LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider);
+
+ /* Sysclk activation on the main PLL */
+ LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);
+ while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1)
+ {
+ /* Wait for system clock switch to PLL */
+ }
+
+ /* Set APBn prescaler*/
+ LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider);
+ LL_RCC_SetAPB2Prescaler(UTILS_ClkInitStruct->APB2CLKDivider);
+ LL_RCC_SetAPB3Prescaler(UTILS_ClkInitStruct->APB3CLKDivider);
+ LL_RCC_SetAPB4Prescaler(UTILS_ClkInitStruct->APB4CLKDivider);
+
+ /* Decreasing the number of wait states because of lower CPU frequency */
+ if (SystemD2Clock > new_hclk_frequency)
+ {
+ /* Set FLASH latency to lowest latency */
+ status = LL_SetFlashLatency(new_hclk_frequency);
+ }
+
+ /* Update the SystemD2Clock global variable */
+#if defined(RCC_D1CFGR_HPRE)
+ SystemD2Clock = (SYSCLK_Frequency >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE)>> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
+#else
+ SystemD2Clock = (SYSCLK_Frequency >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE)>> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU));
+#endif
+
+ /* Update SystemCoreClock variable */
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ LL_SetSystemCoreClock(SystemD2Clock);
+#else
+ LL_SetSystemCoreClock(SYSCLK_Frequency);
+#endif /* DUAL_CORE && CORE_CM4 */
+
+ }
+
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/