diff --git a/stm32/f103c8t6/stm32f1xx_hal_adc.c b/stm32/f103c8t6/stm32f1xx_hal_adc.c
new file mode 100644
index 0000000..62cc847
--- /dev/null
+++ b/stm32/f103c8t6/stm32f1xx_hal_adc.c
@@ -0,0 +1,2437 @@
+/**
+ ******************************************************************************
+ * @file stm32f1xx_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
+ * ++ Channels configuration on injected group
+ * ++ Analog Watchdog configuration
+ * + State functions
+ * ++ ADC state machine management
+ * ++ Interrupts and flags management
+ * Other functions (extended functions) are available in file
+ * "stm32f1xx_hal_adc_ex.c".
+ *
+ @verbatim
+ ==============================================================================
+ ##### ADC peripheral features #####
+ ==============================================================================
+ [..]
+ (+) 12-bit resolution
+
+ (+) Interrupt generation at the end of regular conversion, end of injected
+ 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)
+
+ (+) ADC conversion of regular group and injected group.
+
+ (+) External trigger (timer or EXTI)
+ for both regular and injected groups.
+
+ (+) DMA request generation for transfer of conversions data of regular group.
+
+ (+) Multimode Dual mode (available on devices with 2 ADCs or more).
+
+ (+) Configurable DMA data storage in Multimode Dual mode (available on devices
+ with 2 DCs or more).
+
+ (+) Configurable delay between conversions in Dual interleaved mode (available
+ on devices with 2 DCs or more).
+
+ (+) ADC calibration
+
+ (+) ADC supply requirements: 2.4 V to 3.6 V at full speed and down to 1.8 V at
+ slower speed.
+
+ (+) ADC input range: 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.
+ Caution: On STM32F1, ADC clock frequency max is 14MHz (refer
+ to device datasheet).
+ Therefore, ADC clock prescaler must be configured in
+ function of ADC clock source frequency to remain below
+ this maximum frequency.
+ (++) One clock setting is mandatory:
+ ADC clock (core clock, also possibly conversion clock).
+ (+++) Example:
+ Into HAL_ADC_MspInit() (recommended code location) or with
+ other device clock parameters configuration:
+ (+++) RCC_PeriphCLKInitTypeDef PeriphClkInit;
+ (+++) __ADC1_CLK_ENABLE();
+ (+++) PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
+ (+++) PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV2;
+ (+++) HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
+
+ (#) 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, groups regular/injected, channels parameters ***
+ ==========================================================================
+ [..]
+
+ (#) Configure the ADC parameters (resolution, data alignment, ...)
+ and regular group parameters (conversion trigger, sequencer, ...)
+ using function HAL_ADC_Init().
+
+ (#) Configure the channels for regular group parameters (channel number,
+ channel rank into sequencer, ..., into regular group)
+ using function HAL_ADC_ConfigChannel().
+
+ (#) Optionally, configure the injected group parameters (conversion trigger,
+ sequencer, ..., of injected group)
+ and the channels for injected group parameters (channel number,
+ channel rank into sequencer, ..., into injected group)
+ using function HAL_ADCEx_InjectedConfigChannel().
+
+ (#) Optionally, configure the analog watchdog parameters (channels
+ monitored, thresholds, ...)
+ using function HAL_ADC_AnalogWDGConfig().
+
+ (#) Optionally, for devices with several ADC instances: configure the
+ multimode parameters
+ using function HAL_ADCEx_MultiModeConfigChannel().
+
+ *** Execution of ADC conversions ***
+ ====================================
+ [..]
+
+ (#) 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()
+ (or for injected group: HAL_ADCEx_InjectedPollForConversion() )
+ (+++) Retrieve conversion results
+ using function HAL_ADC_GetValue()
+ (or for injected group: HAL_ADCEx_InjectedGetValue() )
+ (+++) 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)
+ (or for injected group: HAL_ADCEx_InjectedConvCpltCallback() )
+ (+++) Retrieve conversion results
+ using function HAL_ADC_GetValue()
+ (or for injected group: HAL_ADCEx_InjectedGetValue() )
+ (+++) 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()
+
+ (++) For devices with several ADCs: ADC multimode conversion
+ with transfer by DMA:
+ (+++) Activate the ADC peripheral (slave) and start conversions
+ using function HAL_ADC_Start()
+ (+++) Activate the ADC peripheral (master) and start conversions
+ using function HAL_ADCEx_MultiModeStart_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 (master)
+ using function HAL_ADCEx_MultiModeStop_DMA()
+ (+++) Stop conversion and disable the ADC peripheral (slave)
+ using function HAL_ADC_Stop_IT()
+
+ [..]
+
+ (@) Callback functions must be implemented in user program:
+ (+@) HAL_ADC_ErrorCallback()
+ (+@) HAL_ADC_LevelOutOfWindowCallback() (callback of analog watchdog)
+ (+@) HAL_ADC_ConvCpltCallback()
+ (+@) HAL_ADC_ConvHalfCpltCallback
+ (+@) HAL_ADCEx_InjectedConvCpltCallback()
+
+ *** Deinitialization of ADC ***
+ ============================================================
+ [..]
+
+ (#) Disable the ADC interface
+ (++) ADC clock can be hard reset and disabled at RCC top level.
+ (++) Hard reset of ADC peripherals
+ using macro __ADCx_FORCE_RESET(), __ADCx_RELEASE_RESET().
+ (++) ADC clock disable
+ using the equivalent macro/functions as configuration step.
+ (+++) Example:
+ Into HAL_ADC_MspDeInit() (recommended code location) or with
+ other device clock parameters configuration:
+ (+++) PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC
+ (+++) PeriphClkInit.AdcClockSelection = RCC_ADCPLLCLK2_OFF
+ (+++) 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
+ (+) 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
+ (+) 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
+ *
+ *
© Copyright (c) 2016 STMicroelectronics.
+ * All rights reserved.
+ *
+ * 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 "stm32f1xx_hal.h"
+
+/** @addtogroup STM32F1xx_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
+ * @{
+ */
+
+ /* Timeout values for ADC enable and disable settling time. */
+ /* Values defined to be higher than worst cases: low clocks freq, */
+ /* maximum prescaler. */
+ /* Ex of profile low frequency : Clock source at 0.1 MHz, ADC clock */
+ /* prescaler 4, sampling time 12.5 ADC clock cycles, resolution 12 bits. */
+ /* Unit: ms */
+ #define ADC_ENABLE_TIMEOUT 2U
+ #define ADC_DISABLE_TIMEOUT 2U
+
+ /* Delay for ADC stabilization time. */
+ /* Maximum delay is 1us (refer to device datasheet, parameter tSTAB). */
+ /* Unit: us */
+ #define ADC_STAB_DELAY_US 1U
+
+ /* Delay for temperature sensor stabilization time. */
+ /* Maximum delay is 10us (refer to device datasheet, parameter tSTART). */
+ /* Unit: us */
+ #define ADC_TEMPSENSOR_DELAY_US 10U
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup ADC_Private_Functions ADC Private Functions
+ * @{
+ */
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup ADC_Exported_Functions ADC Exported Functions
+ * @{
+ */
+
+/** @defgroup ADC_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 and configure the ADC.
+ (+) De-initialize the ADC.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes 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
+ * (clock source APB2).
+ * See commented example code below that can be copied and uncommented
+ * into HAL_ADC_MspInit().
+ * @note Possibility to update parameters on the fly:
+ * This function initializes the ADC MSP (HAL_ADC_MspInit()) only when
+ * coming from ADC state reset. Following calls to this function can
+ * be used to reconfigure some parameters of ADC_InitTypeDef
+ * structure on the fly, without modifying MSP configuration. If ADC
+ * MSP has to be modified again, HAL_ADC_DeInit() must be called
+ * before HAL_ADC_Init().
+ * The setting of these parameters is conditioned to ADC state.
+ * For parameters constraints, see comments of structure
+ * "ADC_InitTypeDef".
+ * @note This function configures the ADC within 2 scopes: scope of entire
+ * ADC and scope of regular group. For parameters details, see comments
+ * of structure "ADC_InitTypeDef".
+ * @param hadc: ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ uint32_t tmp_cr1 = 0U;
+ uint32_t tmp_cr2 = 0U;
+ uint32_t tmp_sqr1 = 0U;
+
+ /* Check ADC handle */
+ if(hadc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_DATA_ALIGN(hadc->Init.DataAlign));
+ assert_param(IS_ADC_SCAN_MODE(hadc->Init.ScanConvMode));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_EXTTRIG(hadc->Init.ExternalTrigConv));
+
+ 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 != DISABLE)
+ {
+ assert_param(IS_ADC_REGULAR_DISCONT_NUMBER(hadc->Init.NbrOfDiscConversion));
+ }
+ }
+
+ /* As prerequisite, into HAL_ADC_MspInit(), ADC clock must be configured */
+ /* at RCC top level. */
+ /* Refer to header of this file for more details on clock enabling */
+ /* procedure. */
+
+ /* Actions performed only if ADC is coming from state reset: */
+ /* - Initialization of ADC MSP */
+ if (hadc->State == HAL_ADC_STATE_RESET)
+ {
+ /* Initialize ADC error code */
+ ADC_CLEAR_ERRORCODE(hadc);
+
+ /* Allocate lock resource and initialize it */
+ hadc->Lock = HAL_UNLOCKED;
+
+#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 */
+
+ 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 */
+ }
+
+ /* Stop potential conversion on going, on regular and injected groups */
+ /* Disable ADC peripheral */
+ /* Note: In case of ADC already enabled, precaution to not launch an */
+ /* unwanted conversion while modifying register CR2 by writing 1 to */
+ /* bit ADON. */
+ tmp_hal_status = ADC_ConversionStop_Disable(hadc);
+
+
+ /* Configuration of ADC parameters if previous preliminary actions are */
+ /* correctly completed. */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL) &&
+ (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);
+
+ /* Set ADC parameters */
+
+ /* Configuration of ADC: */
+ /* - data alignment */
+ /* - external trigger to start conversion */
+ /* - external trigger polarity (always set to 1, because needed for all */
+ /* triggers: external trigger of SW start) */
+ /* - continuous conversion mode */
+ /* Note: External trigger polarity (ADC_CR2_EXTTRIG) is set into */
+ /* HAL_ADC_Start_xxx functions because if set in this function, */
+ /* a conversion on injected group would start a conversion also on */
+ /* regular group after ADC enabling. */
+ tmp_cr2 |= (hadc->Init.DataAlign |
+ ADC_CFGR_EXTSEL(hadc, hadc->Init.ExternalTrigConv) |
+ ADC_CR2_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode) );
+
+ /* Configuration of ADC: */
+ /* - scan mode */
+ /* - discontinuous mode disable/enable */
+ /* - discontinuous mode number of conversions */
+ tmp_cr1 |= (ADC_CR1_SCAN_SET(hadc->Init.ScanConvMode));
+
+ /* Enable discontinuous mode only if continuous mode is disabled */
+ /* Note: If parameter "Init.ScanConvMode" is set to disable, parameter */
+ /* discontinuous is set anyway, but will have no effect on ADC HW. */
+ if (hadc->Init.DiscontinuousConvMode == ENABLE)
+ {
+ if (hadc->Init.ContinuousConvMode == DISABLE)
+ {
+ /* Enable the selected ADC regular discontinuous mode */
+ /* Set the number of channels to be converted in discontinuous mode */
+ SET_BIT(tmp_cr1, ADC_CR1_DISCEN |
+ ADC_CR1_DISCONTINUOUS_NUM(hadc->Init.NbrOfDiscConversion) );
+ }
+ else
+ {
+ /* ADC regular group settings continuous and sequencer discontinuous*/
+ /* cannot be enabled simultaneously. */
+
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Set ADC error code to ADC IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+ }
+ }
+
+ /* Update ADC configuration register CR1 with previous settings */
+ MODIFY_REG(hadc->Instance->CR1,
+ ADC_CR1_SCAN |
+ ADC_CR1_DISCEN |
+ ADC_CR1_DISCNUM ,
+ tmp_cr1 );
+
+ /* Update ADC configuration register CR2 with previous settings */
+ MODIFY_REG(hadc->Instance->CR2,
+ ADC_CR2_ALIGN |
+ ADC_CR2_EXTSEL |
+ ADC_CR2_EXTTRIG |
+ ADC_CR2_CONT ,
+ tmp_cr2 );
+
+ /* 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 present by hardware on this device and, if */
+ /* disabled, discards automatically nb of conversions. Anyway, nb of */
+ /* conversions is forced to 0x00 for alignment over all STM32 devices. */
+ /* - if scan mode is enabled, regular channels sequence length is set to */
+ /* parameter "NbrOfConversion" */
+ if (ADC_CR1_SCAN_SET(hadc->Init.ScanConvMode) == ADC_SCAN_ENABLE)
+ {
+ tmp_sqr1 = ADC_SQR1_L_SHIFT(hadc->Init.NbrOfConversion);
+ }
+
+ MODIFY_REG(hadc->Instance->SQR1,
+ ADC_SQR1_L ,
+ tmp_sqr1 );
+
+ /* Check back that ADC registers have effectively been configured to */
+ /* ensure of no potential problem of ADC core IP clocking. */
+ /* Check through register CR2 (excluding bits set in other functions: */
+ /* execution control bits (ADON, JSWSTART, SWSTART), regular group bits */
+ /* (DMA), injected group bits (JEXTTRIG and JEXTSEL), channel internal */
+ /* measurement path bit (TSVREFE). */
+ if (READ_BIT(hadc->Instance->CR2, ~(ADC_CR2_ADON | ADC_CR2_DMA |
+ ADC_CR2_SWSTART | ADC_CR2_JSWSTART |
+ ADC_CR2_JEXTTRIG | ADC_CR2_JEXTSEL |
+ ADC_CR2_TSVREFE ))
+ == tmp_cr2)
+ {
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+
+ /* Set the ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_BUSY_INTERNAL,
+ HAL_ADC_STATE_READY);
+ }
+ else
+ {
+ /* Update ADC state machine to error */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_BUSY_INTERNAL,
+ HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ }
+ 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.
+ * If needed, the example code can be copied and uncommented into
+ * function HAL_ADC_MspDeInit().
+ * @param hadc: ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* 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, on regular and injected groups */
+ /* Disable ADC peripheral */
+ tmp_hal_status = ADC_ConversionStop_Disable(hadc);
+
+
+ /* Configuration of ADC parameters if previous preliminary actions are */
+ /* correctly completed. */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* ========== Reset ADC registers ========== */
+
+
+
+
+ /* Reset register SR */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_AWD | ADC_FLAG_JEOC | ADC_FLAG_EOC |
+ ADC_FLAG_JSTRT | ADC_FLAG_STRT));
+
+ /* Reset register CR1 */
+ CLEAR_BIT(hadc->Instance->CR1, (ADC_CR1_AWDEN | ADC_CR1_JAWDEN | ADC_CR1_DISCNUM |
+ ADC_CR1_JDISCEN | ADC_CR1_DISCEN | ADC_CR1_JAUTO |
+ ADC_CR1_AWDSGL | ADC_CR1_SCAN | ADC_CR1_JEOCIE |
+ ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_AWDCH ));
+
+ /* Reset register CR2 */
+ CLEAR_BIT(hadc->Instance->CR2, (ADC_CR2_TSVREFE | ADC_CR2_SWSTART | ADC_CR2_JSWSTART |
+ ADC_CR2_EXTTRIG | ADC_CR2_EXTSEL | ADC_CR2_JEXTTRIG |
+ ADC_CR2_JEXTSEL | ADC_CR2_ALIGN | ADC_CR2_DMA |
+ ADC_CR2_RSTCAL | ADC_CR2_CAL | ADC_CR2_CONT |
+ ADC_CR2_ADON ));
+
+ /* Reset register SMPR1 */
+ CLEAR_BIT(hadc->Instance->SMPR1, (ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16 | ADC_SMPR1_SMP15 |
+ ADC_SMPR1_SMP14 | ADC_SMPR1_SMP13 | ADC_SMPR1_SMP12 |
+ ADC_SMPR1_SMP11 | ADC_SMPR1_SMP10 ));
+
+ /* Reset register SMPR2 */
+ CLEAR_BIT(hadc->Instance->SMPR2, (ADC_SMPR2_SMP9 | ADC_SMPR2_SMP8 | ADC_SMPR2_SMP7 |
+ ADC_SMPR2_SMP6 | ADC_SMPR2_SMP5 | ADC_SMPR2_SMP4 |
+ ADC_SMPR2_SMP3 | ADC_SMPR2_SMP2 | ADC_SMPR2_SMP1 |
+ ADC_SMPR2_SMP0 ));
+
+ /* Reset register JOFR1 */
+ CLEAR_BIT(hadc->Instance->JOFR1, ADC_JOFR1_JOFFSET1);
+ /* Reset register JOFR2 */
+ CLEAR_BIT(hadc->Instance->JOFR2, ADC_JOFR2_JOFFSET2);
+ /* Reset register JOFR3 */
+ CLEAR_BIT(hadc->Instance->JOFR3, ADC_JOFR3_JOFFSET3);
+ /* Reset register JOFR4 */
+ CLEAR_BIT(hadc->Instance->JOFR4, ADC_JOFR4_JOFFSET4);
+
+ /* Reset register HTR */
+ CLEAR_BIT(hadc->Instance->HTR, ADC_HTR_HT);
+ /* Reset register LTR */
+ CLEAR_BIT(hadc->Instance->LTR, ADC_LTR_LT);
+
+ /* Reset register SQR1 */
+ CLEAR_BIT(hadc->Instance->SQR1, ADC_SQR1_L |
+ ADC_SQR1_SQ16 | ADC_SQR1_SQ15 |
+ ADC_SQR1_SQ14 | ADC_SQR1_SQ13 );
+
+ /* Reset register SQR1 */
+ CLEAR_BIT(hadc->Instance->SQR1, ADC_SQR1_L |
+ ADC_SQR1_SQ16 | ADC_SQR1_SQ15 |
+ ADC_SQR1_SQ14 | ADC_SQR1_SQ13 );
+
+ /* Reset register SQR2 */
+ CLEAR_BIT(hadc->Instance->SQR2, ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10 |
+ ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7 );
+
+ /* Reset register SQR3 */
+ CLEAR_BIT(hadc->Instance->SQR3, ADC_SQR3_SQ6 | ADC_SQR3_SQ5 | ADC_SQR3_SQ4 |
+ ADC_SQR3_SQ3 | ADC_SQR3_SQ2 | ADC_SQR3_SQ1 );
+
+ /* Reset register JSQR */
+ CLEAR_BIT(hadc->Instance->JSQR, ADC_JSQR_JL |
+ ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 |
+ ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1 );
+
+ /* Reset register JSQR */
+ CLEAR_BIT(hadc->Instance->JSQR, ADC_JSQR_JL |
+ ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 |
+ ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1 );
+
+ /* Reset register DR */
+ /* bits in access mode read only, no direct reset applicable*/
+
+ /* Reset registers JDR1, JDR2, JDR3, JDR4 */
+ /* bits in access mode read only, no direct reset applicable*/
+
+ /* ========== Hard reset ADC peripheral ========== */
+ /* Performs a global reset of the entire ADC peripheral: ADC state is */
+ /* forced to a similar state after device power-on. */
+ /* If needed, copy-paste and uncomment the following reset code into */
+ /* function "void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)": */
+ /* */
+ /* __HAL_RCC_ADC1_FORCE_RESET() */
+ /* __HAL_RCC_ADC1_RELEASE_RESET() */
+
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ if (hadc->MspDeInitCallback == NULL)
+ {
+ hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware */
+ hadc->MspDeInitCallback(hadc);
+#else
+ /* DeInit the low level hardware */
+ HAL_ADC_MspDeInit(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+
+ /* Set ADC state */
+ hadc->State = HAL_ADC_STATE_RESET;
+
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Initializes 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 DeInitializes the ADC MSP.
+ * @param hadc: ADC handle
+ * @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 complete 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_MSPINIT_CB_ID ADC Msp Init callback ID
+ * @arg @ref HAL_ADC_MSPDEINIT_CB_ID ADC Msp DeInit callback ID
+ * @arg @ref HAL_ADC_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_ADC_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_RegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID, pADC_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ if ((hadc->State & HAL_ADC_STATE_READY) != 0)
+ {
+ 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_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 complete 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_MSPINIT_CB_ID ADC Msp Init callback ID
+ * @arg @ref HAL_ADC_MSPDEINIT_CB_ID ADC Msp DeInit callback ID
+ * @arg @ref HAL_ADC_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_ADC_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_UnRegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if ((hadc->State & HAL_ADC_STATE_READY) != 0)
+ {
+ 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_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 IO operation functions
+ * @brief Input and Output 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 Enables ADC, starts conversion of regular group.
+ * Interruptions enabled in this function: None.
+ * @param hadc: ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* 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_BUSY);
+
+ /* Set group injected state (from auto-injection) and multimode state */
+ /* for all cases of multimode: independent mode, multimode ADC master */
+ /* or multimode ADC slave (for devices with several ADCs): */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ /* Set ADC state (ADC independent or master) */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+
+ /* If conversions on group regular are also triggering group injected, */
+ /* update ADC state. */
+ if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+ else
+ {
+ /* Set ADC state (ADC slave) */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+
+ /* If conversions on group regular are also triggering group injected, */
+ /* update ADC state. */
+ if (ADC_MULTIMODE_AUTO_INJECTED(hadc))
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* State machine update: Check if an injected conversion is ongoing */
+ if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ /* Reset ADC error code fields related to conversions on group regular */
+ CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
+ }
+ else
+ {
+ /* Reset ADC all error code fields */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* Clear regular group conversion flag */
+ /* (To ensure of no unknown state from potential previous ADC operations) */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC);
+
+ /* 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: */
+ /* - if ADC is slave, ADC is enabled only (conversion is not started). */
+ /* - if ADC is master, ADC is enabled and conversion is started. */
+ /* If ADC is master, ADC is enabled and conversion is started. */
+ /* Note: Alternate trigger for single conversion could be to force an */
+ /* additional set of bit ADON "hadc->Instance->CR2 |= ADC_CR2_ADON;"*/
+ if (ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
+ ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc) )
+ {
+ /* Start ADC conversion on regular group with SW start */
+ SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG));
+ }
+ else
+ {
+ /* Start ADC conversion on regular group with external trigger */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG);
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ /* 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 = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Stop potential conversion on going, on regular and injected groups */
+ /* Disable ADC peripheral */
+ tmp_hal_status = ADC_ConversionStop_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 This function cannot be used in a particular setup: ADC configured
+ * in DMA mode.
+ * In this case, DMA resets the flag EOC and polling cannot be
+ * performed on each conversion.
+ * @note On STM32F1 devices, limitation in case of sequencer enabled
+ * (several ranks selected): polling cannot be done on each
+ * conversion inside the sequence. In this case, polling is replaced by
+ * wait for maximum conversion time.
+ * @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 = 0U;
+
+ /* Variables for polling in case of scan mode enabled and polling for each */
+ /* conversion. */
+ __IO uint32_t Conversion_Timeout_CPU_cycles = 0U;
+ uint32_t Conversion_Timeout_CPU_cycles_max = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Get tick count */
+ tickstart = HAL_GetTick();
+
+ /* Verification that ADC configuration is compliant with polling for */
+ /* each conversion: */
+ /* Particular case is ADC configured in DMA mode */
+ if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_DMA))
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Polling for end of conversion: differentiation if single/sequence */
+ /* conversion. */
+ /* - If single conversion for regular group (Scan mode disabled or enabled */
+ /* with NbrOfConversion =1), flag EOC is used to determine the */
+ /* conversion completion. */
+ /* - If sequence conversion for regular group (scan mode enabled and */
+ /* NbrOfConversion >=2), flag EOC is set only at the end of the */
+ /* sequence. */
+ /* To poll for each conversion, the maximum conversion time is computed */
+ /* from ADC conversion time (selected sampling time + conversion time of */
+ /* 12.5 ADC clock cycles) and APB2/ADC clock prescalers (depending on */
+ /* settings, conversion time range can be from 28 to 32256 CPU cycles). */
+ /* As flag EOC is not set after each conversion, no timeout status can */
+ /* be set. */
+ if (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_SCAN) &&
+ HAL_IS_BIT_CLR(hadc->Instance->SQR1, ADC_SQR1_L) )
+ {
+ /* Wait until End of Conversion flag is raised */
+ while(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_EOC))
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0U) || ((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_EOC))
+ {
+ /* Update ADC state machine to timeout */
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Replace polling by wait for maximum conversion time */
+ /* - Computation of CPU clock cycles corresponding to ADC clock cycles */
+ /* and ADC maximum conversion cycles on all channels. */
+ /* - Wait for the expected ADC clock cycles delay */
+ Conversion_Timeout_CPU_cycles_max = ((SystemCoreClock
+ / HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_ADC))
+ * ADC_CONVCYCLES_MAX_RANGE(hadc) );
+
+ while(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max)
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max)
+ {
+ /* Update ADC state machine to timeout */
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ Conversion_Timeout_CPU_cycles ++;
+ }
+ }
+
+ /* Clear regular group conversion flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_STRT | ADC_FLAG_EOC);
+
+ /* 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. */
+ /* Note: On STM32F1 devices, in case of sequencer enabled */
+ /* (several ranks selected), end of conversion flag is raised */
+ /* at the end of the sequence. */
+ if(ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
+ (hadc->Init.ContinuousConvMode == DISABLE) )
+ {
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+
+ /* Return ADC state */
+ return HAL_OK;
+}
+
+/**
+ * @brief Poll for conversion event.
+ * @param hadc: ADC handle
+ * @param EventType: the ADC event type.
+ * This parameter can be one of the following values:
+ * @arg ADC_AWD_EVENT: ADC Analog watchdog event.
+ * @param Timeout: Timeout value in millisecond.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout)
+{
+ uint32_t tickstart = 0U;
+
+ /* 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) == RESET)
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0U) || ((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if(__HAL_ADC_GET_FLAG(hadc, EventType) == RESET)
+ {
+ /* Update ADC state machine to timeout */
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Analog watchdog (level out of window) event */
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+
+ /* Clear ADC analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD);
+
+ /* Return ADC state */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables ADC, starts conversion of regular group with interruption.
+ * Interruptions enabled in this function:
+ * - EOC (end of conversion of regular group)
+ * Each of these interruptions has its dedicated callback function.
+ * @param hadc: ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_hal_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ /* - Clear state bitfield related to regular group conversion results */
+ /* - Set state bitfield related to regular operation */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
+ HAL_ADC_STATE_REG_BUSY);
+
+ /* Set group injected state (from auto-injection) and multimode state */
+ /* for all cases of multimode: independent mode, multimode ADC master */
+ /* or multimode ADC slave (for devices with several ADCs): */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ /* Set ADC state (ADC independent or master) */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+
+ /* If conversions on group regular are also triggering group injected, */
+ /* update ADC state. */
+ if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+ else
+ {
+ /* Set ADC state (ADC slave) */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+
+ /* If conversions on group regular are also triggering group injected, */
+ /* update ADC state. */
+ if (ADC_MULTIMODE_AUTO_INJECTED(hadc))
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* State machine update: Check if an injected conversion is ongoing */
+ if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ /* Reset ADC error code fields related to conversions on group regular */
+ CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
+ }
+ else
+ {
+ /* Reset ADC all error code fields */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* 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);
+
+ /* Enable end of conversion interrupt for regular group */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOC);
+
+ /* 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: */
+ /* - if ADC is slave, ADC is enabled only (conversion is not started). */
+ /* - if ADC is master, ADC is enabled and conversion is started. */
+ if (ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
+ ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc) )
+ {
+ /* Start ADC conversion on regular group with SW start */
+ SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG));
+ }
+ else
+ {
+ /* Start ADC conversion on regular group with external trigger */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG);
+ }
+ }
+ else
+ {
+ /* 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 interrution of
+ * end-of-conversion, disable ADC peripheral.
+ * @param hadc: ADC handle
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Stop potential conversion on going, on regular and injected groups */
+ /* Disable ADC peripheral */
+ tmp_hal_status = ADC_ConversionStop_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Disable ADC end of conversion interrupt for regular group */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC);
+
+ /* 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 Enables ADC, starts conversion of regular group and transfers result
+ * through DMA.
+ * Interruptions enabled in this function:
+ * - DMA transfer complete
+ * - DMA half transfer
+ * Each of these interruptions has its dedicated callback function.
+ * @note For devices with several ADCs: This function is for single-ADC mode
+ * only. For multimode, use the dedicated MultimodeStart function.
+ * @note On STM32F1 devices, only ADC1 and ADC3 (ADC availability depending
+ * on devices) have DMA capability.
+ * ADC2 converted data can be transferred in dual ADC mode using DMA
+ * of ADC1 (ADC master in multimode).
+ * In case of using ADC1 with DMA on a device featuring 2 ADC
+ * instances: ADC1 conversion register DR contains ADC1 conversion
+ * result (ADC1 register DR bits 0 to 11) and, additionally, ADC2 last
+ * conversion result (ADC1 register DR bits 16 to 27). Therefore, to
+ * have DMA transferring the conversion results of ADC1 only, DMA must
+ * be configured to transfer size: half word.
+ * @param hadc: ADC handle
+ * @param pData: The destination Buffer address.
+ * @param Length: The length of data to be transferred from ADC peripheral to memory.
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_DMA_CAPABILITY_INSTANCE(hadc->Instance));
+
+ /* Verification if multimode is disabled (for devices with several ADC) */
+ /* If multimode is enabled, dedicated function multimode conversion */
+ /* start DMA must be used. */
+ if(ADC_MULTIMODE_IS_ENABLE(hadc) == RESET)
+ {
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_hal_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state */
+ /* - Clear state bitfield related to regular group conversion results */
+ /* - Set state bitfield related to regular operation */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
+ HAL_ADC_STATE_REG_BUSY);
+
+ /* Set group injected state (from auto-injection) and multimode state */
+ /* for all cases of multimode: independent mode, multimode ADC master */
+ /* or multimode ADC slave (for devices with several ADCs): */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ /* Set ADC state (ADC independent or master) */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+
+ /* If conversions on group regular are also triggering group injected, */
+ /* update ADC state. */
+ if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+ else
+ {
+ /* Set ADC state (ADC slave) */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+
+ /* If conversions on group regular are also triggering group injected, */
+ /* update ADC state. */
+ if (ADC_MULTIMODE_AUTO_INJECTED(hadc))
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* State machine update: Check if an injected conversion is ongoing */
+ if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ /* Reset ADC error code fields related to conversions on group regular */
+ CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
+ }
+ else
+ {
+ /* Reset ADC all error code fields */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(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);
+
+ /* Enable ADC DMA mode */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_DMA);
+
+ /* Start the DMA channel */
+ HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);
+
+ /* Enable conversion of regular group. */
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ if (ADC_IS_SOFTWARE_START_REGULAR(hadc))
+ {
+ /* Start ADC conversion on regular group with SW start */
+ SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG));
+ }
+ else
+ {
+ /* Start ADC conversion on regular group with external trigger */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG);
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+ }
+ else
+ {
+ tmp_hal_status = HAL_ERROR;
+ }
+
+ /* 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 injected group. If injected group is under use, it
+ * should be preliminarily stopped using HAL_ADCEx_InjectedStop function.
+ * @note For devices with several ADCs: This function is for single-ADC mode
+ * only. For multimode, use the dedicated MultimodeStop function.
+ * @note On STM32F1 devices, only ADC1 and ADC3 (ADC availability depending
+ * on devices) have DMA capability.
+ * @param hadc: ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_DMA_CAPABILITY_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Stop potential conversion on going, on regular and injected groups */
+ /* Disable ADC peripheral */
+ tmp_hal_status = ADC_ConversionStop_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Disable ADC DMA mode */
+ CLEAR_BIT(hadc->Instance->CR2, ADC_CR2_DMA);
+
+ /* 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)
+ {
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+ }
+ }
+ }
+
+ /* 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 Handles ADC interrupt request
+ * @param hadc: ADC handle
+ * @retval None
+ */
+void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_REGULAR_NB_CONV(hadc->Init.NbrOfConversion));
+
+
+ /* ========== Check End of Conversion flag for regular group ========== */
+ if(__HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_EOC))
+ {
+ if(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC) )
+ {
+ /* Update state machine on conversion status if not in error state */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL))
+ {
+ /* 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. */
+ /* Note: On STM32F1 devices, in case of sequencer enabled */
+ /* (several ranks selected), end of conversion flag is raised */
+ /* at the end of the sequence. */
+ if(ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
+ (hadc->Init.ContinuousConvMode == DISABLE) )
+ {
+ /* Disable ADC end of conversion interrupt on group regular */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC);
+
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+
+ /* Conversion complete callback */
+#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 */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_STRT | ADC_FLAG_EOC);
+ }
+ }
+
+ /* ========== Check End of Conversion flag for injected group ========== */
+ if(__HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_JEOC))
+ {
+ if(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOC))
+ {
+ /* Update state machine on conversion status if not in error state */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL))
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC);
+ }
+
+ /* Determine whether any further conversion upcoming on group injected */
+ /* by external trigger, scan sequence on going or by automatic injected */
+ /* conversion from group regular (same conditions as group regular */
+ /* interruption disabling above). */
+ /* Note: On STM32F1 devices, in case of sequencer enabled */
+ /* (several ranks selected), end of conversion flag is raised */
+ /* at the end of the sequence. */
+ if(ADC_IS_SOFTWARE_START_INJECTED(hadc) ||
+ (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) &&
+ (ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
+ (hadc->Init.ContinuousConvMode == DISABLE) ) ) )
+ {
+ /* Disable ADC end of conversion interrupt on group injected */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC);
+
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+
+ /* Conversion complete callback */
+#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_JSTRT | ADC_FLAG_JEOC));
+ }
+ }
+
+ /* ========== Check Analog watchdog flags ========== */
+ if(__HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_AWD))
+ {
+ if(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_AWD))
+ {
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+
+ /* Level out of window callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->LevelOutOfWindowCallback(hadc);
+#else
+ HAL_ADC_LevelOutOfWindowCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+ /* Clear the ADC analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD);
+ }
+ }
+
+}
+
+/**
+ * @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 callback in non blocking mode.
+ * @param hadc: ADC handle
+ * @retval None
+ */
+__weak void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADC_LevelOutOfWindowCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief ADC error callback in non blocking mode
+ * (ADC conversion with interruption or transfer by DMA)
+ * @param hadc: ADC handle
+ * @retval None
+ */
+__weak void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hadc);
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_ADC_ErrorCallback must be implemented in the user file.
+ */
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure channels on regular group
+ (+) Configure the analog watchdog
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the the selected channel to be linked to the regular
+ * group.
+ * @note In case of usage of internal measurement channels:
+ * Vbat/VrefInt/TempSensor.
+ * These internal paths can be be disabled using function
+ * HAL_ADC_DeInit().
+ * @note Possibility to update parameters on the fly:
+ * This function initializes channel into regular group, following
+ * calls to this function can be used to reconfigure some parameters
+ * of structure "ADC_ChannelConfTypeDef" on the fly, without reseting
+ * the ADC.
+ * The setting of these parameters is conditioned to ADC state.
+ * For parameters constraints, see comments of structure
+ * "ADC_ChannelConfTypeDef".
+ * @param hadc: ADC handle
+ * @param sConfig: Structure of ADC channel for regular group.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ __IO uint32_t wait_loop_index = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_CHANNEL(sConfig->Channel));
+ assert_param(IS_ADC_REGULAR_RANK(sConfig->Rank));
+ assert_param(IS_ADC_SAMPLE_TIME(sConfig->SamplingTime));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+
+ /* Regular sequence configuration */
+ /* For Rank 1 to 6 */
+ if (sConfig->Rank < 7U)
+ {
+ MODIFY_REG(hadc->Instance->SQR3 ,
+ ADC_SQR3_RK(ADC_SQR3_SQ1, sConfig->Rank) ,
+ ADC_SQR3_RK(sConfig->Channel, sConfig->Rank) );
+ }
+ /* For Rank 7 to 12 */
+ else if (sConfig->Rank < 13U)
+ {
+ MODIFY_REG(hadc->Instance->SQR2 ,
+ ADC_SQR2_RK(ADC_SQR2_SQ7, sConfig->Rank) ,
+ ADC_SQR2_RK(sConfig->Channel, sConfig->Rank) );
+ }
+ /* For Rank 13 to 16 */
+ else
+ {
+ MODIFY_REG(hadc->Instance->SQR1 ,
+ ADC_SQR1_RK(ADC_SQR1_SQ13, sConfig->Rank) ,
+ ADC_SQR1_RK(sConfig->Channel, sConfig->Rank) );
+ }
+
+
+ /* Channel sampling time configuration */
+ /* For channels 10 to 17 */
+ if (sConfig->Channel >= ADC_CHANNEL_10)
+ {
+ MODIFY_REG(hadc->Instance->SMPR1 ,
+ ADC_SMPR1(ADC_SMPR1_SMP10, sConfig->Channel) ,
+ ADC_SMPR1(sConfig->SamplingTime, sConfig->Channel) );
+ }
+ else /* For channels 0 to 9 */
+ {
+ MODIFY_REG(hadc->Instance->SMPR2 ,
+ ADC_SMPR2(ADC_SMPR2_SMP0, sConfig->Channel) ,
+ ADC_SMPR2(sConfig->SamplingTime, sConfig->Channel) );
+ }
+
+ /* If ADC1 Channel_16 or Channel_17 is selected, enable Temperature sensor */
+ /* and VREFINT measurement path. */
+ if ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) ||
+ (sConfig->Channel == ADC_CHANNEL_VREFINT) )
+ {
+ /* For STM32F1 devices with several ADC: Only ADC1 can access internal */
+ /* measurement channels (VrefInt/TempSensor). If these channels are */
+ /* intended to be set on other ADC instances, an error is reported. */
+ if (hadc->Instance == ADC1)
+ {
+ if (READ_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE) == RESET)
+ {
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE);
+
+ if (sConfig->Channel == ADC_CHANNEL_TEMPSENSOR)
+ {
+ /* Delay for temperature sensor stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ wait_loop_index = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000U));
+ while(wait_loop_index != 0U)
+ {
+ wait_loop_index--;
+ }
+ }
+ }
+ }
+ 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 Configures the analog watchdog.
+ * @note Analog watchdog thresholds can be modified while ADC conversion
+ * is on going.
+ * In this case, some constraints must be taken into account:
+ * the programmed threshold values are effective from the next
+ * ADC EOC (end of unitary conversion).
+ * Considering that registers write delay may happen due to
+ * bus activity, this might cause an uncertainty on the
+ * effective timing of the new programmed threshold values.
+ * @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)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_ANALOG_WATCHDOG_MODE(AnalogWDGConfig->WatchdogMode));
+ assert_param(IS_FUNCTIONAL_STATE(AnalogWDGConfig->ITMode));
+ assert_param(IS_ADC_RANGE(AnalogWDGConfig->HighThreshold));
+ assert_param(IS_ADC_RANGE(AnalogWDGConfig->LowThreshold));
+
+ 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));
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Analog watchdog configuration */
+
+ /* Configure ADC Analog watchdog interrupt */
+ if(AnalogWDGConfig->ITMode == ENABLE)
+ {
+ /* Enable the ADC Analog watchdog interrupt */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_AWD);
+ }
+ else
+ {
+ /* Disable the ADC Analog watchdog interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_AWD);
+ }
+
+ /* Configuration of analog watchdog: */
+ /* - Set the analog watchdog enable mode: regular and/or injected groups, */
+ /* one or all channels. */
+ /* - Set the Analog watchdog channel (is not used if watchdog */
+ /* mode "all channels": ADC_CFGR_AWD1SGL=0). */
+ MODIFY_REG(hadc->Instance->CR1 ,
+ ADC_CR1_AWDSGL |
+ ADC_CR1_JAWDEN |
+ ADC_CR1_AWDEN |
+ ADC_CR1_AWDCH ,
+ AnalogWDGConfig->WatchdogMode |
+ AnalogWDGConfig->Channel );
+
+ /* Set the high threshold */
+ WRITE_REG(hadc->Instance->HTR, AnalogWDGConfig->HighThreshold);
+
+ /* Set the low threshold */
+ WRITE_REG(hadc->Instance->LTR, AnalogWDGConfig->LowThreshold);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_Exported_Functions_Group4 Peripheral State functions
+ * @brief 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 state
+ * @param hadc: ADC handle
+ * @retval HAL state
+ */
+uint32_t HAL_ADC_GetState(ADC_HandleTypeDef* hadc)
+{
+ /* Return ADC state */
+ return hadc->State;
+}
+
+/**
+ * @brief Return the ADC error code
+ * @param hadc: ADC handle
+ * @retval ADC Error Code
+ */
+uint32_t HAL_ADC_GetError(ADC_HandleTypeDef *hadc)
+{
+ return hadc->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Private_Functions ADC Private Functions
+ * @{
+ */
+
+/**
+ * @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 = 0U;
+ __IO uint32_t wait_loop_index = 0U;
+
+ /* 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 (ADC_IS_ENABLE(hadc) == RESET)
+ {
+ /* Enable the Peripheral */
+ __HAL_ADC_ENABLE(hadc);
+
+ /* Delay for ADC stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ wait_loop_index = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U));
+ while(wait_loop_index != 0U)
+ {
+ wait_loop_index--;
+ }
+
+ /* Get tick count */
+ tickstart = HAL_GetTick();
+
+ /* Wait for ADC effectively enabled */
+ while(ADC_IS_ENABLE(hadc) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if(ADC_IS_ENABLE(hadc) == RESET)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop ADC conversion and disable the selected ADC
+ * @note Prerequisite condition to use this function: ADC conversions must be
+ * stopped to disable the ADC.
+ * @param hadc: ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef ADC_ConversionStop_Disable(ADC_HandleTypeDef* hadc)
+{
+ uint32_t tickstart = 0U;
+
+ /* Verification if ADC is not already disabled */
+ if (ADC_IS_ENABLE(hadc) != RESET)
+ {
+ /* Disable the ADC peripheral */
+ __HAL_ADC_DISABLE(hadc);
+
+ /* Get tick count */
+ tickstart = HAL_GetTick();
+
+ /* Wait for ADC effectively disabled */
+ while(ADC_IS_ENABLE(hadc) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > ADC_DISABLE_TIMEOUT)
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if(ADC_IS_ENABLE(hadc) != RESET)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Return HAL status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DMA transfer complete callback.
+ * @param hdma: pointer to DMA handle.
+ * @retval None
+ */
+void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Retrieve ADC handle corresponding to current DMA handle */
+ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Update state machine on conversion status if not in error state */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL | HAL_ADC_STATE_ERROR_DMA))
+ {
+ /* Update ADC state machine */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+
+ /* Determine whether any further conversion upcoming on group regular */
+ /* by external trigger, continuous mode or scan sequence on going. */
+ /* Note: On STM32F1 devices, in case of sequencer enabled */
+ /* (several ranks selected), end of conversion flag is raised */
+ /* at the end of the sequence. */
+ if(ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
+ (hadc->Init.ContinuousConvMode == DISABLE) )
+ {
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+
+ /* Conversion complete callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->ConvCpltCallback(hadc);
+#else
+ HAL_ADC_ConvCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Call DMA error callback */
+ hadc->DMA_Handle->XferErrorCallback(hdma);
+ }
+}
+
+/**
+ * @brief DMA half transfer complete callback.
+ * @param hdma: pointer to DMA handle.
+ * @retval None
+ */
+void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Retrieve ADC handle corresponding to current DMA handle */
+ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Half conversion callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->ConvHalfCpltCallback(hadc);
+#else
+ HAL_ADC_ConvHalfCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA error callback
+ * @param hdma: pointer to DMA handle.
+ * @retval None
+ */
+void ADC_DMAError(DMA_HandleTypeDef *hdma)
+{
+ /* Retrieve ADC handle corresponding to current DMA handle */
+ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Set ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+
+ /* Set ADC error code to DMA error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_DMA);
+
+ /* Error callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+ hadc->ErrorCallback(hadc);
+#else
+ HAL_ADC_ErrorCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm32/f103c8t6/stm32f1xx_hal_adc_ex.c b/stm32/f103c8t6/stm32f1xx_hal_adc_ex.c
new file mode 100644
index 0000000..dc7408a
--- /dev/null
+++ b/stm32/f103c8t6/stm32f1xx_hal_adc_ex.c
@@ -0,0 +1,1337 @@
+/**
+ ******************************************************************************
+ * @file stm32f1xx_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 injected
+ * group, using 2 possible modes: polling, interruption.
+ * ++ Multimode feature (available on devices with 2 ADCs or more)
+ * ++ Calibration (ADC automatic self-calibration)
+ * + Control functions
+ * ++ Channels configuration on injected group
+ * Other functions (generic functions) are available in file
+ * "stm32f1xx_hal_adc.c".
+ *
+ @verbatim
+ [..]
+ (@) Sections "ADC peripheral features" and "How to use this driver" are
+ available in file of generic functions "stm32f1xx_hal_adc.c".
+ [..]
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2016 STMicroelectronics.
+ * All rights reserved.
+ *
+ * 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 "stm32f1xx_hal.h"
+
+/** @addtogroup STM32F1xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup ADCEx ADCEx
+ * @brief ADC Extension HAL module driver
+ * @{
+ */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup ADCEx_Private_Constants ADCEx Private Constants
+ * @{
+ */
+
+ /* Delay for ADC calibration: */
+ /* Hardware prerequisite before starting a calibration: the ADC must have */
+ /* been in power-on state for at least two ADC clock cycles. */
+ /* Unit: ADC clock cycles */
+ #define ADC_PRECALIBRATION_DELAY_ADCCLOCKCYCLES 2U
+
+ /* Timeout value for ADC calibration */
+ /* Value defined to be higher than worst cases: low clocks freq, */
+ /* maximum prescaler. */
+ /* Ex of profile low frequency : Clock source at 0.1 MHz, ADC clock */
+ /* prescaler 4, sampling time 12.5 ADC clock cycles, resolution 12 bits. */
+ /* Unit: ms */
+ #define ADC_CALIBRATION_TIMEOUT 10U
+
+ /* Delay for temperature sensor stabilization time. */
+ /* Maximum delay is 10us (refer to device datasheet, parameter tSTART). */
+ /* Unit: us */
+ #define ADC_TEMPSENSOR_DELAY_US 10U
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup ADCEx_Exported_Functions ADCEx Exported Functions
+ * @{
+ */
+
+/** @defgroup ADCEx_Exported_Functions_Group1 Extended Extended IO operation functions
+ * @brief Extended Extended Input and Output operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start conversion of injected group.
+ (+) Stop conversion of injected group.
+ (+) Poll for conversion complete on injected group.
+ (+) Get result of injected channel conversion.
+ (+) Start conversion of injected group and enable interruptions.
+ (+) Stop conversion of injected group and disable interruptions.
+
+ (+) Start multimode and enable DMA transfer.
+ (+) Stop multimode and disable ADC DMA transfer.
+ (+) Get result of multimode conversion.
+
+ (+) 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.
+
+@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() ).
+ * During calibration process, ADC is enabled. ADC is let enabled at
+ * the completion of this function.
+ * @param hadc: ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ uint32_t tickstart;
+ __IO uint32_t wait_loop_index = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Calibration prerequisite: */
+ /* - ADC must be disabled for at least two ADC clock cycles in disable */
+ /* mode before ADC enable */
+ /* Stop potential conversion on going, on regular and injected groups */
+ /* Disable ADC peripheral */
+ tmp_hal_status = ADC_ConversionStop_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);
+
+ /* Hardware prerequisite: delay before starting the calibration. */
+ /* - Computation of CPU clock cycles corresponding to ADC clock cycles. */
+ /* - Wait for the expected ADC clock cycles delay */
+ wait_loop_index = ((SystemCoreClock
+ / HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_ADC))
+ * ADC_PRECALIBRATION_DELAY_ADCCLOCKCYCLES );
+
+ while(wait_loop_index != 0U)
+ {
+ wait_loop_index--;
+ }
+
+ /* 2. Enable the ADC peripheral */
+ ADC_Enable(hadc);
+
+ /* 3. Resets ADC calibration registers */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_RSTCAL);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait for calibration reset completion */
+ while(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_RSTCAL))
+ {
+ if((HAL_GetTick() - tickstart) > ADC_CALIBRATION_TIMEOUT)
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_RSTCAL))
+ {
+ /* 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;
+ }
+ }
+ }
+
+ /* 4. Start ADC calibration */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_CAL);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait for calibration completion */
+ while(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_CAL))
+ {
+ if((HAL_GetTick() - tickstart) > ADC_CALIBRATION_TIMEOUT)
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_CAL))
+ {
+ /* 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);
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_hal_status;
+}
+
+/**
+ * @brief Enables ADC, starts conversion of injected group.
+ * Interruptions enabled in this function: None.
+ * @param hadc: ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* 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 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);
+
+ /* Case of independent mode or multimode (for devices with several ADCs): */
+ /* Set multimode state. */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+ else
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* Check if a regular conversion is ongoing */
+ /* Note: On this device, there is no ADC error code fields related to */
+ /* conversions on group injected only. In case of conversion on */
+ /* going on group regular, no error code is reset. */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
+ {
+ /* Reset ADC all error code fields */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* Clear injected group conversion flag */
+ /* (To ensure of no unknown state from potential previous ADC operations) */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC);
+
+ /* Enable conversion of injected group. */
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ /* If automatic injected conversion is enabled, conversion will start */
+ /* after next regular group conversion. */
+ /* Case of multimode enabled (for devices with several ADCs): if ADC is */
+ /* slave, ADC is enabled only (conversion is not started). If ADC is */
+ /* master, ADC is enabled and conversion is started. */
+ if (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO))
+ {
+ if (ADC_IS_SOFTWARE_START_INJECTED(hadc) &&
+ ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc) )
+ {
+ /* Start ADC conversion on injected group with SW start */
+ SET_BIT(hadc->Instance->CR2, (ADC_CR2_JSWSTART | ADC_CR2_JEXTTRIG));
+ }
+ else
+ {
+ /* Start ADC conversion on injected group with external trigger */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_JEXTTRIG);
+ }
+ }
+ }
+ 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 auto-injection mode, HAL_ADC_Stop must be used.
+ * @param hadc: ADC handle
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Stop potential conversion and disable ADC peripheral */
+ /* Conditioned to: */
+ /* - No conversion on the other group (regular group) is intended to */
+ /* continue (injected and regular groups stop conversion and ADC disable */
+ /* are common) */
+ /* - In case of auto-injection mode, HAL_ADC_Stop must be used. */
+ if(((hadc->State & HAL_ADC_STATE_REG_BUSY) == RESET) &&
+ HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) )
+ {
+ /* Stop potential conversion on going, on regular and injected groups */
+ /* Disable ADC peripheral */
+ tmp_hal_status = ADC_ConversionStop_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);
+ }
+ }
+ 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 Wait for injected group conversion to be completed.
+ * @param hadc: ADC handle
+ * @param Timeout: Timeout value in millisecond.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Variables for polling in case of scan mode enabled and polling for each */
+ /* conversion. */
+ __IO uint32_t Conversion_Timeout_CPU_cycles = 0U;
+ uint32_t Conversion_Timeout_CPU_cycles_max = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Polling for end of conversion: differentiation if single/sequence */
+ /* conversion. */
+ /* For injected group, flag JEOC is set only at the end of the sequence, */
+ /* not for each conversion within the sequence. */
+ /* - If single conversion for injected group (scan mode disabled or */
+ /* InjectedNbrOfConversion ==1), flag JEOC is used to determine the */
+ /* conversion completion. */
+ /* - If sequence conversion for injected group (scan mode enabled and */
+ /* InjectedNbrOfConversion >=2), flag JEOC is set only at the end of the */
+ /* sequence. */
+ /* To poll for each conversion, the maximum conversion time is computed */
+ /* from ADC conversion time (selected sampling time + conversion time of */
+ /* 12.5 ADC clock cycles) and APB2/ADC clock prescalers (depending on */
+ /* settings, conversion time range can be from 28 to 32256 CPU cycles). */
+ /* As flag JEOC is not set after each conversion, no timeout status can */
+ /* be set. */
+ if ((hadc->Instance->JSQR & ADC_JSQR_JL) == RESET)
+ {
+ /* Wait until End of Conversion flag is raised */
+ while(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_JEOC))
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0U) || ((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_JEOC))
+ {
+ /* Update ADC state machine to timeout */
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Replace polling by wait for maximum conversion time */
+ /* - Computation of CPU clock cycles corresponding to ADC clock cycles */
+ /* and ADC maximum conversion cycles on all channels. */
+ /* - Wait for the expected ADC clock cycles delay */
+ Conversion_Timeout_CPU_cycles_max = ((SystemCoreClock
+ / HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_ADC))
+ * ADC_CONVCYCLES_MAX_RANGE(hadc) );
+
+ while(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max)
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max)
+ {
+ /* Update ADC state machine to timeout */
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ Conversion_Timeout_CPU_cycles ++;
+ }
+ }
+
+ /* Clear injected group conversion flag */
+ /* Note: On STM32F1 ADC, clear regular conversion flag raised */
+ /* simultaneously. */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JSTRT | ADC_FLAG_JEOC | ADC_FLAG_EOC);
+
+ /* 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(ADC_IS_SOFTWARE_START_INJECTED(hadc) ||
+ (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) &&
+ (ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
+ (hadc->Init.ContinuousConvMode == DISABLE) ) ) )
+ {
+ /* Set ADC state */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+
+ /* Return ADC state */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables ADC, starts conversion of injected group with interruption.
+ * - JEOC (end of conversion of injected group)
+ * Each of these interruptions has its dedicated callback function.
+ * @param hadc: ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* 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 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);
+
+ /* Case of independent mode or multimode (for devices with several ADCs): */
+ /* Set multimode state. */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+ else
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* Check if a regular conversion is ongoing */
+ /* Note: On this device, there is no ADC error code fields related to */
+ /* conversions on group injected only. In case of conversion on */
+ /* going on group regular, no error code is reset. */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
+ {
+ /* Reset ADC all error code fields */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* Clear injected group conversion flag */
+ /* (To ensure of no unknown state from potential previous ADC operations) */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC);
+
+ /* Enable end of conversion interrupt for injected channels */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);
+
+ /* Start conversion of injected group if software start has been selected */
+ /* and if automatic injected conversion is disabled. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ /* If automatic injected conversion is enabled, conversion will start */
+ /* after next regular group conversion. */
+ if (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO))
+ {
+ if (ADC_IS_SOFTWARE_START_INJECTED(hadc) &&
+ ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc) )
+ {
+ /* Start ADC conversion on injected group with SW start */
+ SET_BIT(hadc->Instance->CR2, (ADC_CR2_JSWSTART | ADC_CR2_JEXTTRIG));
+ }
+ else
+ {
+ /* Start ADC conversion on injected group with external trigger */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_JEXTTRIG);
+ }
+ }
+ }
+ 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.
+ * @param hadc: ADC handle
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Stop potential conversion and disable ADC peripheral */
+ /* Conditioned to: */
+ /* - No conversion on the other group (regular group) is intended to */
+ /* continue (injected and regular groups stop conversion and ADC disable */
+ /* are common) */
+ /* - In case of auto-injection mode, HAL_ADC_Stop must be used. */
+ if(((hadc->State & HAL_ADC_STATE_REG_BUSY) == RESET) &&
+ HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) )
+ {
+ /* Stop potential conversion on going, on regular and injected groups */
+ /* Disable ADC peripheral */
+ tmp_hal_status = ADC_ConversionStop_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Disable ADC end of conversion interrupt for injected channels */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC);
+
+ /* Set ADC state */
+ ADC_STATE_CLR_SET(hadc->State,
+ HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+ HAL_ADC_STATE_READY);
+ }
+ }
+ 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;
+}
+
+#if defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F105xC) || defined (STM32F107xC) || defined (STM32F103xE) || defined (STM32F103xG)
+/**
+ * @brief Enables ADC, starts conversion of regular group and transfers result
+ * through DMA.
+ * Multimode must have been previously configured using
+ * HAL_ADCEx_MultiModeConfigChannel() function.
+ * Interruptions enabled in this function:
+ * - DMA transfer complete
+ * - DMA half transfer
+ * Each of these interruptions has its dedicated callback function.
+ * @note: On STM32F1 devices, ADC slave regular group must be configured
+ * with conversion trigger ADC_SOFTWARE_START.
+ * @note: ADC slave can be enabled preliminarily using single-mode
+ * HAL_ADC_Start() function.
+ * @param hadc: ADC handle of ADC master (handle of ADC slave must not be used)
+ * @param pData: The destination Buffer address.
+ * @param Length: The length of data to be transferred from ADC peripheral to memory.
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ ADC_HandleTypeDef tmphadcSlave={0};
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Set a temporary handle of the ADC slave associated to the ADC master */
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ /* On STM32F1 devices, ADC slave regular group must be configured with */
+ /* conversion trigger ADC_SOFTWARE_START. */
+ /* Note: External trigger of ADC slave must be enabled, it is already done */
+ /* into function "HAL_ADC_Init()". */
+ if(!ADC_IS_SOFTWARE_START_REGULAR(&tmphadcSlave))
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the ADC peripherals: master and slave (in case if not already */
+ /* enabled previously) */
+ tmp_hal_status = ADC_Enable(hadc);
+ if (tmp_hal_status == HAL_OK)
+ {
+ tmp_hal_status = ADC_Enable(&tmphadcSlave);
+ }
+
+ /* Start conversion if all ADCs of multimode are effectively enabled */
+ if (tmp_hal_status == HAL_OK)
+ {
+ /* Set ADC state (ADC master) */
+ /* - 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_MULTIMODE_SLAVE,
+ HAL_ADC_STATE_REG_BUSY);
+
+ /* If conversions on group regular are also triggering group injected, */
+ /* update ADC state. */
+ if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+
+ /* Process unlocked */
+ /* Unlock before starting ADC conversions: in case of potential */
+ /* interruption, to let the process to ADC IRQ Handler. */
+ __HAL_UNLOCK(hadc);
+
+ /* 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;
+
+
+ /* 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);
+
+ /* Enable ADC DMA mode of ADC master */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_DMA);
+
+ /* Start the DMA channel */
+ HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);
+
+ /* Start conversion of regular group if software start has been selected. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ /* Note: Alternate trigger for single conversion could be to force an */
+ /* additional set of bit ADON "hadc->Instance->CR2 |= ADC_CR2_ADON;"*/
+ if (ADC_IS_SOFTWARE_START_REGULAR(hadc))
+ {
+ /* Start ADC conversion on regular group with SW start */
+ SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG));
+ }
+ else
+ {
+ /* Start ADC conversion on regular group with external trigger */
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG);
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ /* 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 DMA transfer, disable
+ * ADC peripheral.
+ * @note Multimode is kept enabled after this function. To disable multimode
+ * (set with HAL_ADCEx_MultiModeConfigChannel(), ADC must be
+ * reinitialized using HAL_ADC_Init() or HAL_ADC_ReInit().
+ * @note In case of DMA configured in circular mode, function
+ * HAL_ADC_Stop_DMA must be called after this function with handle of
+ * ADC slave, to properly disable the DMA channel.
+ * @param hadc: ADC handle of ADC master (handle of ADC slave must not be used)
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ ADC_HandleTypeDef tmphadcSlave={0};
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Stop potential conversion on going, on regular and injected groups */
+ /* Disable ADC master peripheral */
+ tmp_hal_status = ADC_ConversionStop_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if(tmp_hal_status == HAL_OK)
+ {
+ /* Set a temporary handle of the ADC slave associated to the ADC master */
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ /* Disable ADC slave peripheral */
+ tmp_hal_status = ADC_ConversionStop_Disable(&tmphadcSlave);
+
+ /* Check if ADC is effectively disabled */
+ if(tmp_hal_status != HAL_OK)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Disable ADC DMA mode */
+ CLEAR_BIT(hadc->Instance->CR2, ADC_CR2_DMA);
+
+ /* Reset configuration of ADC DMA continuous request for dual mode */
+ CLEAR_BIT(hadc->Instance->CR1, ADC_CR1_DUALMOD);
+
+ /* 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);
+
+ /* Change 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;
+}
+#endif /* defined STM32F103x6 || defined STM32F103xB || defined STM32F105xC || defined STM32F107xC || defined STM32F103xE || defined STM32F103xG */
+
+/**
+ * @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 ADC_INJECTED_RANK_1: Injected Channel1 selected
+ * @arg ADC_INJECTED_RANK_2: Injected Channel2 selected
+ * @arg ADC_INJECTED_RANK_3: Injected Channel3 selected
+ * @arg ADC_INJECTED_RANK_4: Injected Channel4 selected
+ * @retval ADC group injected conversion data
+ */
+uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef* hadc, uint32_t InjectedRank)
+{
+ uint32_t tmp_jdr = 0U;
+
+ /* 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;
+}
+
+#if defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F105xC) || defined (STM32F107xC) || defined (STM32F103xE) || defined (STM32F103xG)
+/**
+ * @brief Returns the last ADC Master&Slave regular conversions results data
+ * in the selected multi mode.
+ * @param hadc: ADC handle of ADC master (handle of ADC slave must not be used)
+ * @retval The converted data value.
+ */
+uint32_t HAL_ADCEx_MultiModeGetValue(ADC_HandleTypeDef* hadc)
+{
+ uint32_t tmpDR = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+
+ /* 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. */
+
+ /* On STM32F1 devices, ADC1 data register DR contains ADC2 conversions */
+ /* only if ADC1 DMA mode is enabled. */
+ tmpDR = hadc->Instance->DR;
+
+ if (HAL_IS_BIT_CLR(ADC1->CR2, ADC_CR2_DMA))
+ {
+ tmpDR |= (ADC2->DR << 16U);
+ }
+
+ /* Return ADC converted value */
+ return tmpDR;
+}
+#endif /* defined STM32F103x6 || defined STM32F103xB || defined STM32F105xC || defined STM32F107xC || defined STM32F103xE || defined STM32F103xG */
+
+/**
+ * @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,
+ the HAL_ADCEx_InjectedConvCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ADCEx_Exported_Functions_Group2 Extended Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure channels on injected group
+ (+) Configure multimode
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the ADC injected group and the selected channel to be
+ * linked to the injected group.
+ * @note Possibility to update parameters on the fly:
+ * This function initializes injected group, following calls to this
+ * function can be used to reconfigure some parameters of structure
+ * "ADC_InjectionConfTypeDef" on the fly, without reseting the ADC.
+ * The setting of these parameters is conditioned to ADC state:
+ * this function must be called when ADC is not under conversion.
+ * @param hadc: ADC handle
+ * @param sConfigInjected: Structure of ADC injected group and ADC channel for
+ * injected group.
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef* hadc, ADC_InjectionConfTypeDef* sConfigInjected)
+{
+ HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+ __IO uint32_t wait_loop_index = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_CHANNEL(sConfigInjected->InjectedChannel));
+ assert_param(IS_ADC_SAMPLE_TIME(sConfigInjected->InjectedSamplingTime));
+ assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->AutoInjectedConv));
+ assert_param(IS_ADC_EXTTRIGINJEC(sConfigInjected->ExternalTrigInjecConv));
+ assert_param(IS_ADC_RANGE(sConfigInjected->InjectedOffset));
+
+ 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));
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Configuration of injected group sequencer: */
+ /* - if scan mode is disabled, injected channels sequence length is set to */
+ /* 0x00: 1 channel converted (channel on regular rank 1) */
+ /* Parameter "InjectedNbrOfConversion" is discarded. */
+ /* Note: Scan mode is present by hardware on this device and, if */
+ /* disabled, discards automatically nb of conversions. Anyway, nb of */
+ /* conversions is forced to 0x00 for alignment over all STM32 devices. */
+ /* - if scan mode is enabled, injected channels sequence length is set to */
+ /* parameter "InjectedNbrOfConversion". */
+ if (hadc->Init.ScanConvMode == ADC_SCAN_DISABLE)
+ {
+ if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1)
+ {
+ /* Clear the old SQx bits for all injected ranks */
+ MODIFY_REG(hadc->Instance->JSQR ,
+ ADC_JSQR_JL |
+ ADC_JSQR_JSQ4 |
+ ADC_JSQR_JSQ3 |
+ ADC_JSQR_JSQ2 |
+ ADC_JSQR_JSQ1 ,
+ ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel,
+ ADC_INJECTED_RANK_1,
+ 0x01U));
+ }
+ /* If another injected rank than rank1 was intended to be set, and could */
+ /* not due to ScanConvMode disabled, error is reported. */
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Since injected channels rank conv. order depends on total number of */
+ /* injected conversions, selected rank must be below or equal to total */
+ /* number of injected conversions to be updated. */
+ if (sConfigInjected->InjectedRank <= sConfigInjected->InjectedNbrOfConversion)
+ {
+ /* Clear the old SQx bits for the selected rank */
+ /* Set the SQx bits for the selected rank */
+ MODIFY_REG(hadc->Instance->JSQR ,
+
+ ADC_JSQR_JL |
+ ADC_JSQR_RK_JL(ADC_JSQR_JSQ1,
+ sConfigInjected->InjectedRank,
+ sConfigInjected->InjectedNbrOfConversion) ,
+
+ ADC_JSQR_JL_SHIFT(sConfigInjected->InjectedNbrOfConversion) |
+ ADC_JSQR_RK_JL(sConfigInjected->InjectedChannel,
+ sConfigInjected->InjectedRank,
+ sConfigInjected->InjectedNbrOfConversion) );
+ }
+ else
+ {
+ /* Clear the old SQx bits for the selected rank */
+ MODIFY_REG(hadc->Instance->JSQR ,
+
+ ADC_JSQR_JL |
+ ADC_JSQR_RK_JL(ADC_JSQR_JSQ1,
+ sConfigInjected->InjectedRank,
+ sConfigInjected->InjectedNbrOfConversion) ,
+
+ 0x00000000U);
+ }
+ }
+
+ /* Configuration of injected group */
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated only when ADC is disabled: */
+ /* - external trigger to start conversion */
+ /* Parameters update not conditioned to ADC state: */
+ /* - Automatic injected conversion */
+ /* - Injected discontinuous mode */
+ /* Note: In case of ADC already enabled, caution to not launch an unwanted */
+ /* conversion while modifying register CR2 by writing 1 to bit ADON. */
+ if (ADC_IS_ENABLE(hadc) == RESET)
+ {
+ MODIFY_REG(hadc->Instance->CR2 ,
+ ADC_CR2_JEXTSEL |
+ ADC_CR2_ADON ,
+ ADC_CFGR_JEXTSEL(hadc, sConfigInjected->ExternalTrigInjecConv) );
+ }
+
+
+ /* Configuration of injected group */
+ /* - Automatic injected conversion */
+ /* - Injected discontinuous mode */
+
+ /* Automatic injected conversion can be enabled if injected group */
+ /* external triggers are disabled. */
+ if (sConfigInjected->AutoInjectedConv == ENABLE)
+ {
+ if (sConfigInjected->ExternalTrigInjecConv == ADC_INJECTED_SOFTWARE_START)
+ {
+ SET_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO);
+ }
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+ }
+
+ /* Injected discontinuous can be enabled only if auto-injected mode is */
+ /* disabled. */
+ if (sConfigInjected->InjectedDiscontinuousConvMode == ENABLE)
+ {
+ if (sConfigInjected->AutoInjectedConv == DISABLE)
+ {
+ SET_BIT(hadc->Instance->CR1, ADC_CR1_JDISCEN);
+ }
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_hal_status = HAL_ERROR;
+ }
+ }
+
+
+ /* InjectedChannel sampling time configuration */
+ /* For channels 10 to 17 */
+ if (sConfigInjected->InjectedChannel >= ADC_CHANNEL_10)
+ {
+ MODIFY_REG(hadc->Instance->SMPR1 ,
+ ADC_SMPR1(ADC_SMPR1_SMP10, sConfigInjected->InjectedChannel) ,
+ ADC_SMPR1(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel) );
+ }
+ else /* For channels 0 to 9 */
+ {
+ MODIFY_REG(hadc->Instance->SMPR2 ,
+ ADC_SMPR2(ADC_SMPR2_SMP0, sConfigInjected->InjectedChannel) ,
+ ADC_SMPR2(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel) );
+ }
+
+ /* If ADC1 InjectedChannel_16 or InjectedChannel_17 is selected, enable Temperature sensor */
+ /* and VREFINT measurement path. */
+ if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) ||
+ (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) )
+ {
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE);
+ }
+
+
+ /* Configure the offset: offset enable/disable, InjectedChannel, offset value */
+ switch(sConfigInjected->InjectedRank)
+ {
+ case 1:
+ /* Set injected channel 1 offset */
+ MODIFY_REG(hadc->Instance->JOFR1,
+ ADC_JOFR1_JOFFSET1,
+ sConfigInjected->InjectedOffset);
+ break;
+ case 2:
+ /* Set injected channel 2 offset */
+ MODIFY_REG(hadc->Instance->JOFR2,
+ ADC_JOFR2_JOFFSET2,
+ sConfigInjected->InjectedOffset);
+ break;
+ case 3:
+ /* Set injected channel 3 offset */
+ MODIFY_REG(hadc->Instance->JOFR3,
+ ADC_JOFR3_JOFFSET3,
+ sConfigInjected->InjectedOffset);
+ break;
+ case 4:
+ default:
+ MODIFY_REG(hadc->Instance->JOFR4,
+ ADC_JOFR4_JOFFSET4,
+ sConfigInjected->InjectedOffset);
+ break;
+ }
+
+ /* If ADC1 Channel_16 or Channel_17 is selected, enable Temperature sensor */
+ /* and VREFINT measurement path. */
+ if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) ||
+ (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) )
+ {
+ /* For STM32F1 devices with several ADC: Only ADC1 can access internal */
+ /* measurement channels (VrefInt/TempSensor). If these channels are */
+ /* intended to be set on other ADC instances, an error is reported. */
+ if (hadc->Instance == ADC1)
+ {
+ if (READ_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE) == RESET)
+ {
+ SET_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE);
+
+ if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR))
+ {
+ /* Delay for temperature sensor stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ wait_loop_index = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000U));
+ while(wait_loop_index != 0U)
+ {
+ wait_loop_index--;
+ }
+ }
+ }
+ }
+ 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;
+}
+
+#if defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F105xC) || defined (STM32F107xC) || defined (STM32F103xE) || defined (STM32F103xG)
+/**
+ * @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 reseting
+ * the ADCs (both ADCs of the common group).
+ * The setting of these parameters is conditioned to ADC state.
+ * For parameters constraints, see comments of structure
+ * "ADC_MultiModeTypeDef".
+ * @note To change back configuration from multimode to single mode, ADC must
+ * be reset (using function HAL_ADC_Init() ).
+ * @param hadc: 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_HandleTypeDef tmphadcSlave={0};
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_MODE(multimode->Mode));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Set a temporary handle of the ADC slave associated to the ADC master */
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated when ADC is disabled or enabled without */
+ /* conversion on going on regular group: */
+ /* - ADC master and ADC slave DMA configuration */
+ /* Parameters that can be updated only when ADC is disabled: */
+ /* - Multimode mode selection */
+ /* To optimize code, all multimode settings can be set when both ADCs of */
+ /* the common group are in state: disabled. */
+ if ((ADC_IS_ENABLE(hadc) == RESET) &&
+ (ADC_IS_ENABLE(&tmphadcSlave) == RESET) &&
+ (IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance)) )
+ {
+ MODIFY_REG(hadc->Instance->CR1,
+ ADC_CR1_DUALMOD ,
+ multimode->Mode );
+ }
+ /* 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;
+}
+#endif /* defined STM32F103x6 || defined STM32F103xB || defined STM32F105xC || defined STM32F107xC || defined STM32F103xE || defined STM32F103xG */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm32/f103c8t6/stm32f1xx_hal_flash.c b/stm32/f103c8t6/stm32f1xx_hal_flash.c
new file mode 100644
index 0000000..2a628e8
--- /dev/null
+++ b/stm32/f103c8t6/stm32f1xx_hal_flash.c
@@ -0,0 +1,967 @@
+/**
+ ******************************************************************************
+ * @file stm32f1xx_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 State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### FLASH peripheral features #####
+ ==============================================================================
+ [..] The Flash memory interface manages CPU AHB I-Code and D-Code accesses
+ to the Flash memory. It implements the erase and program Flash memory operations
+ and the read and write protection mechanisms.
+
+ [..] The Flash memory interface accelerates code execution with a system of instruction
+ prefetch.
+
+ [..] The FLASH main features are:
+ (+) Flash memory read operations
+ (+) Flash memory program/erase operations
+ (+) Read / write protections
+ (+) Prefetch on I-Code
+ (+) Option Bytes programming
+
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver provides functions and macros to configure and program the FLASH
+ memory of all STM32F1xx devices.
+
+ (#) FLASH Memory I/O Programming functions: this group includes all needed
+ functions to erase and program the main memory:
+ (++) Lock and Unlock the FLASH interface
+ (++) Erase function: Erase page, erase all pages
+ (++) Program functions: half word, word and doubleword
+ (#) FLASH Option Bytes Programming functions: this group includes all needed
+ functions to manage the Option Bytes:
+ (++) Lock and Unlock the Option Bytes
+ (++) Set/Reset the write protection
+ (++) Set the Read protection Level
+ (++) Program the user Option Bytes
+ (++) Launch the Option Bytes loader
+ (++) Erase Option Bytes
+ (++) Program the data Option Bytes
+ (++) Get the Write protection.
+ (++) Get the user option bytes.
+
+ (#) Interrupts and flags management functions : this group
+ includes all needed functions to:
+ (++) Handle FLASH interrupts
+ (++) Wait for last FLASH operation according to its status
+ (++) Get error flag status
+
+ [..] In addition to these function, this driver includes a set of macros allowing
+ to handle the following operations:
+
+ (+) Set/Get the latency
+ (+) Enable/Disable the prefetch buffer
+ (+) Enable/Disable the half cycle access
+ (+) Enable/Disable the FLASH interrupts
+ (+) Monitor the FLASH flags status
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2016 STMicroelectronics.
+ * All rights reserved.
+ *
+ * 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 "stm32f1xx_hal.h"
+
+/** @addtogroup STM32F1xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/** @defgroup FLASH FLASH
+ * @brief FLASH HAL module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup FLASH_Private_Constants FLASH Private Constants
+ * @{
+ */
+/**
+ * @}
+ */
+
+/* Private macro ---------------------------- ---------------------------------*/
+/** @defgroup FLASH_Private_Macros FLASH Private Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup FLASH_Private_Variables FLASH Private Variables
+ * @{
+ */
+/* Variables used for Erase pages under interruption*/
+FLASH_ProcessTypeDef pFlash;
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup FLASH_Private_Functions FLASH Private Functions
+ * @{
+ */
+static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data);
+static void FLASH_SetErrorCode(void);
+extern void FLASH_PageErase(uint32_t PageAddress);
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+/** @defgroup FLASH_Exported_Functions FLASH Exported Functions
+ * @{
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
+ * @brief Programming operation functions
+ *
+@verbatim
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Program halfword, word or double word at a specified address
+ * @note The function HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
+ * The function HAL_FLASH_Lock() should be called after to lock the FLASH interface
+ *
+ * @note If an erase and a program operations are requested simultaneously,
+ * the erase operation is performed before the program one.
+ *
+ * @note FLASH should be previously erased before new programmation (only exception to this
+ * is when 0x0000 is programmed)
+ *
+ * @param TypeProgram: Indicate the way to program at a specified address.
+ * This parameter can be a value of @ref FLASH_Type_Program
+ * @param Address: Specifies the address to be programmed.
+ * @param Data: Specifies the data to be programmed
+ *
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+ uint8_t index = 0;
+ uint8_t nbiterations = 0;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
+
+#if defined(FLASH_BANK2_END)
+ if(Address <= FLASH_BANK1_END)
+ {
+#endif /* FLASH_BANK2_END */
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+#if defined(FLASH_BANK2_END)
+ }
+ else
+ {
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperationBank2(FLASH_TIMEOUT_VALUE);
+ }
+#endif /* FLASH_BANK2_END */
+
+ if(status == HAL_OK)
+ {
+ if(TypeProgram == FLASH_TYPEPROGRAM_HALFWORD)
+ {
+ /* Program halfword (16-bit) at a specified address. */
+ nbiterations = 1U;
+ }
+ else if(TypeProgram == FLASH_TYPEPROGRAM_WORD)
+ {
+ /* Program word (32-bit = 2*16-bit) at a specified address. */
+ nbiterations = 2U;
+ }
+ else
+ {
+ /* Program double word (64-bit = 4*16-bit) at a specified address. */
+ nbiterations = 4U;
+ }
+
+ for (index = 0U; index < nbiterations; index++)
+ {
+ FLASH_Program_HalfWord((Address + (2U*index)), (uint16_t)(Data >> (16U*index)));
+
+#if defined(FLASH_BANK2_END)
+ if(Address <= FLASH_BANK1_END)
+ {
+#endif /* FLASH_BANK2_END */
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+
+ /* If the program operation is completed, disable the PG Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
+#if defined(FLASH_BANK2_END)
+ }
+ else
+ {
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperationBank2(FLASH_TIMEOUT_VALUE);
+
+ /* If the program operation is completed, disable the PG Bit */
+ CLEAR_BIT(FLASH->CR2, FLASH_CR2_PG);
+ }
+#endif /* FLASH_BANK2_END */
+ /* In case of error, stop programation procedure */
+ if (status != HAL_OK)
+ {
+ break;
+ }
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Program halfword, word or double word at a specified address with interrupt enabled.
+ * @note The function HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
+ * The function HAL_FLASH_Lock() should be called after to lock the FLASH interface
+ *
+ * @note If an erase and a program operations are requested simultaneously,
+ * the erase operation is performed before the program one.
+ *
+ * @param TypeProgram: Indicate the way to program at a specified address.
+ * This parameter can be a value of @ref FLASH_Type_Program
+ * @param Address: Specifies the address to be programmed.
+ * @param Data: Specifies the data to be programmed
+ *
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
+
+#if defined(FLASH_BANK2_END)
+ /* If procedure already ongoing, reject the next one */
+ if (pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
+ {
+ return HAL_ERROR;
+ }
+
+ if(Address <= FLASH_BANK1_END)
+ {
+ /* Enable End of FLASH Operation and Error source interrupts */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP_BANK1 | FLASH_IT_ERR_BANK1);
+
+ }else
+ {
+ /* Enable End of FLASH Operation and Error source interrupts */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP_BANK2 | FLASH_IT_ERR_BANK2);
+ }
+#else
+ /* Enable End of FLASH Operation and Error source interrupts */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
+#endif /* FLASH_BANK2_END */
+
+ pFlash.Address = Address;
+ pFlash.Data = Data;
+
+ if(TypeProgram == FLASH_TYPEPROGRAM_HALFWORD)
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAMHALFWORD;
+ /* Program halfword (16-bit) at a specified address. */
+ pFlash.DataRemaining = 1U;
+ }
+ else if(TypeProgram == FLASH_TYPEPROGRAM_WORD)
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAMWORD;
+ /* Program word (32-bit : 2*16-bit) at a specified address. */
+ pFlash.DataRemaining = 2U;
+ }
+ else
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAMDOUBLEWORD;
+ /* Program double word (64-bit : 4*16-bit) at a specified address. */
+ pFlash.DataRemaining = 4U;
+ }
+
+ /* Program halfword (16-bit) at a specified address. */
+ FLASH_Program_HalfWord(Address, (uint16_t)Data);
+
+ return status;
+}
+
+/**
+ * @brief This function handles FLASH interrupt request.
+ * @retval None
+ */
+void HAL_FLASH_IRQHandler(void)
+{
+ uint32_t addresstmp = 0U;
+
+ /* Check FLASH operation error flags */
+#if defined(FLASH_BANK2_END)
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR_BANK1) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR_BANK1) || \
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR_BANK2) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR_BANK2)))
+#else
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) ||__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
+#endif /* FLASH_BANK2_END */
+ {
+ /* Return the faulty address */
+ addresstmp = pFlash.Address;
+ /* Reset address */
+ pFlash.Address = 0xFFFFFFFFU;
+
+ /* Save the Error code */
+ FLASH_SetErrorCode();
+
+ /* FLASH error interrupt user callback */
+ HAL_FLASH_OperationErrorCallback(addresstmp);
+
+ /* Stop the procedure ongoing */
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ }
+
+ /* Check FLASH End of Operation flag */
+#if defined(FLASH_BANK2_END)
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP_BANK1))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP_BANK1);
+#else
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+#endif /* FLASH_BANK2_END */
+
+ /* Process can continue only if no error detected */
+ if(pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
+ {
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGEERASE)
+ {
+ /* Nb of pages to erased can be decreased */
+ pFlash.DataRemaining--;
+
+ /* Check if there are still pages to erase */
+ if(pFlash.DataRemaining != 0U)
+ {
+ addresstmp = pFlash.Address;
+ /*Indicate user which sector has been erased */
+ HAL_FLASH_EndOfOperationCallback(addresstmp);
+
+ /*Increment sector number*/
+ addresstmp = pFlash.Address + FLASH_PAGE_SIZE;
+ pFlash.Address = addresstmp;
+
+ /* If the erase operation is completed, disable the PER Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
+
+ FLASH_PageErase(addresstmp);
+ }
+ else
+ {
+ /* No more pages to Erase, user callback can be called. */
+ /* Reset Sector and stop Erase pages procedure */
+ pFlash.Address = addresstmp = 0xFFFFFFFFU;
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(addresstmp);
+ }
+ }
+ else if(pFlash.ProcedureOnGoing == FLASH_PROC_MASSERASE)
+ {
+ /* Operation is completed, disable the MER Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_MER);
+
+#if defined(FLASH_BANK2_END)
+ /* Stop Mass Erase procedure if no pending mass erase on other bank */
+ if (HAL_IS_BIT_CLR(FLASH->CR2, FLASH_CR2_MER))
+ {
+#endif /* FLASH_BANK2_END */
+ /* MassErase ended. Return the selected bank */
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(0U);
+
+ /* Stop Mass Erase procedure*/
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ }
+#if defined(FLASH_BANK2_END)
+ }
+#endif /* FLASH_BANK2_END */
+ else
+ {
+ /* Nb of 16-bit data to program can be decreased */
+ pFlash.DataRemaining--;
+
+ /* Check if there are still 16-bit data to program */
+ if(pFlash.DataRemaining != 0U)
+ {
+ /* Increment address to 16-bit */
+ pFlash.Address += 2U;
+ addresstmp = pFlash.Address;
+
+ /* Shift to have next 16-bit data */
+ pFlash.Data = (pFlash.Data >> 16U);
+
+ /* Operation is completed, disable the PG Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
+
+ /*Program halfword (16-bit) at a specified address.*/
+ FLASH_Program_HalfWord(addresstmp, (uint16_t)pFlash.Data);
+ }
+ else
+ {
+ /* Program ended. Return the selected address */
+ /* FLASH EOP interrupt user callback */
+ if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMHALFWORD)
+ {
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address);
+ }
+ else if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMWORD)
+ {
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address - 2U);
+ }
+ else
+ {
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address - 6U);
+ }
+
+ /* Reset Address and stop Program procedure */
+ pFlash.Address = 0xFFFFFFFFU;
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ }
+ }
+ }
+ }
+
+#if defined(FLASH_BANK2_END)
+ /* Check FLASH End of Operation flag */
+ if(__HAL_FLASH_GET_FLAG( FLASH_FLAG_EOP_BANK2))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP_BANK2);
+
+ /* Process can continue only if no error detected */
+ if(pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
+ {
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGEERASE)
+ {
+ /* Nb of pages to erased can be decreased */
+ pFlash.DataRemaining--;
+
+ /* Check if there are still pages to erase*/
+ if(pFlash.DataRemaining != 0U)
+ {
+ /* Indicate user which page address has been erased*/
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address);
+
+ /* Increment page address to next page */
+ pFlash.Address += FLASH_PAGE_SIZE;
+ addresstmp = pFlash.Address;
+
+ /* Operation is completed, disable the PER Bit */
+ CLEAR_BIT(FLASH->CR2, FLASH_CR2_PER);
+
+ FLASH_PageErase(addresstmp);
+ }
+ else
+ {
+ /*No more pages to Erase*/
+
+ /*Reset Address and stop Erase pages procedure*/
+ pFlash.Address = 0xFFFFFFFFU;
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address);
+ }
+ }
+ else if(pFlash.ProcedureOnGoing == FLASH_PROC_MASSERASE)
+ {
+ /* Operation is completed, disable the MER Bit */
+ CLEAR_BIT(FLASH->CR2, FLASH_CR2_MER);
+
+ if (HAL_IS_BIT_CLR(FLASH->CR, FLASH_CR_MER))
+ {
+ /* MassErase ended. Return the selected bank*/
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(0U);
+
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ }
+ }
+ else
+ {
+ /* Nb of 16-bit data to program can be decreased */
+ pFlash.DataRemaining--;
+
+ /* Check if there are still 16-bit data to program */
+ if(pFlash.DataRemaining != 0U)
+ {
+ /* Increment address to 16-bit */
+ pFlash.Address += 2U;
+ addresstmp = pFlash.Address;
+
+ /* Shift to have next 16-bit data */
+ pFlash.Data = (pFlash.Data >> 16U);
+
+ /* Operation is completed, disable the PG Bit */
+ CLEAR_BIT(FLASH->CR2, FLASH_CR2_PG);
+
+ /*Program halfword (16-bit) at a specified address.*/
+ FLASH_Program_HalfWord(addresstmp, (uint16_t)pFlash.Data);
+ }
+ else
+ {
+ /*Program ended. Return the selected address*/
+ /* FLASH EOP interrupt user callback */
+ if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMHALFWORD)
+ {
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address);
+ }
+ else if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMWORD)
+ {
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address-2U);
+ }
+ else
+ {
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address-6U);
+ }
+
+ /* Reset Address and stop Program procedure*/
+ pFlash.Address = 0xFFFFFFFFU;
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ }
+ }
+ }
+ }
+#endif
+
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
+ {
+#if defined(FLASH_BANK2_END)
+ /* Operation is completed, disable the PG, PER and MER Bits for both bank */
+ CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_PER | FLASH_CR_MER));
+ CLEAR_BIT(FLASH->CR2, (FLASH_CR2_PG | FLASH_CR2_PER | FLASH_CR2_MER));
+
+ /* Disable End of FLASH Operation and Error source interrupts for both banks */
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP_BANK1 | FLASH_IT_ERR_BANK1 | FLASH_IT_EOP_BANK2 | FLASH_IT_ERR_BANK2);
+#else
+ /* Operation is completed, disable the PG, PER and MER Bits */
+ CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_PER | FLASH_CR_MER));
+
+ /* Disable End of FLASH Operation and Error source interrupts */
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
+#endif /* FLASH_BANK2_END */
+
+ /* 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: No return value expected
+ * - Pages Erase: Address of the page which has been erased
+ * (if 0xFFFFFFFF, it means that all the selected pages have been erased)
+ * - Program: Address which was selected for data program
+ * @retval none
+ */
+__weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ReturnValue);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief FLASH operation error interrupt callback
+ * @param ReturnValue: The value saved in this parameter depends on the ongoing procedure
+ * - Mass Erase: No return value expected
+ * - Pages Erase: Address of the page which returned an error
+ * - Program: Address which was selected for data program
+ * @retval none
+ */
+__weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ReturnValue);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FLASH_OperationErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
+ * @brief management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the FLASH
+ memory operations.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Unlock the FLASH control register access
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Unlock(void)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
+ {
+ /* Authorize the FLASH Registers access */
+ WRITE_REG(FLASH->KEYR, FLASH_KEY1);
+ WRITE_REG(FLASH->KEYR, FLASH_KEY2);
+
+ /* Verify Flash is unlocked */
+ if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
+ {
+ status = HAL_ERROR;
+ }
+ }
+#if defined(FLASH_BANK2_END)
+ if(READ_BIT(FLASH->CR2, FLASH_CR2_LOCK) != RESET)
+ {
+ /* 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_CR2_LOCK) != RESET)
+ {
+ status = HAL_ERROR;
+ }
+ }
+#endif /* FLASH_BANK2_END */
+
+ return status;
+}
+
+/**
+ * @brief Locks the FLASH control register access
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Lock(void)
+{
+ /* Set the LOCK Bit to lock the FLASH Registers access */
+ SET_BIT(FLASH->CR, FLASH_CR_LOCK);
+
+#if defined(FLASH_BANK2_END)
+ /* Set the LOCK Bit to lock the FLASH BANK2 Registers access */
+ SET_BIT(FLASH->CR2, FLASH_CR2_LOCK);
+
+#endif /* FLASH_BANK2_END */
+ return HAL_OK;
+}
+
+/**
+ * @brief Unlock the FLASH Option Control Registers access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
+{
+ if (HAL_IS_BIT_CLR(FLASH->CR, FLASH_CR_OPTWRE))
+ {
+ /* Authorizes the Option Byte register programming */
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Lock the FLASH Option Control Registers access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
+{
+ /* Clear the OPTWRE Bit to lock the FLASH Option Byte Registers access */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTWRE);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Launch the option byte loading.
+ * @note This function will reset automatically the MCU.
+ * @retval None
+ */
+void HAL_FLASH_OB_Launch(void)
+{
+ /* Initiates a system reset request to launch the option byte loading */
+ HAL_NVIC_SystemReset();
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group3 Peripheral errors functions
+ * @brief Peripheral errors functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection permit to get in run-time errors of the FLASH peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Get the specific FLASH error flag.
+ * @retval FLASH_ErrorCode The returned value can be:
+ * @ref FLASH_Error_Codes
+ */
+uint32_t HAL_FLASH_GetError(void)
+{
+ return pFlash.ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup FLASH_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Program a half-word (16-bit) at a specified address.
+ * @param Address specify the address to be programmed.
+ * @param Data specify the data to be programmed.
+ * @retval None
+ */
+static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data)
+{
+ /* Clean the error context */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+#if defined(FLASH_BANK2_END)
+ if(Address <= FLASH_BANK1_END)
+ {
+#endif /* FLASH_BANK2_END */
+ /* Proceed to program the new data */
+ SET_BIT(FLASH->CR, FLASH_CR_PG);
+#if defined(FLASH_BANK2_END)
+ }
+ else
+ {
+ /* Proceed to program the new data */
+ SET_BIT(FLASH->CR2, FLASH_CR2_PG);
+ }
+#endif /* FLASH_BANK2_END */
+
+ /* Write data in the address */
+ *(__IO uint16_t*)Address = Data;
+}
+
+/**
+ * @brief Wait for a FLASH operation to complete.
+ * @param Timeout maximum flash operation timeout
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
+{
+ /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
+ Even if the FLASH operation fails, the BUSY flag will be reset and an error
+ flag will be set */
+
+ uint32_t tickstart = HAL_GetTick();
+
+ while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Check FLASH End of Operation flag */
+ if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) ||
+ __HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR) ||
+ __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
+ {
+ /*Save the error code*/
+ FLASH_SetErrorCode();
+ return HAL_ERROR;
+ }
+
+ /* There is no error flag set */
+ return HAL_OK;
+}
+
+#if defined(FLASH_BANK2_END)
+/**
+ * @brief Wait for a FLASH BANK2 operation to complete.
+ * @param Timeout maximum flash operation timeout
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef FLASH_WaitForLastOperationBank2(uint32_t Timeout)
+{
+ /* Wait for the FLASH BANK2 operation to complete by polling on BUSY flag to be reset.
+ Even if the FLASH BANK2 operation fails, the BUSY flag will be reset and an error
+ flag will be set */
+
+ uint32_t tickstart = HAL_GetTick();
+
+ while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY_BANK2))
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Check FLASH End of Operation flag */
+ if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP_BANK2))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP_BANK2);
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR_BANK2) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR_BANK2))
+ {
+ /*Save the error code*/
+ FLASH_SetErrorCode();
+ return HAL_ERROR;
+ }
+
+ /* If there is an error flag set */
+ return HAL_OK;
+
+}
+#endif /* FLASH_BANK2_END */
+
+/**
+ * @brief Set the specific FLASH error flag.
+ * @retval None
+ */
+static void FLASH_SetErrorCode(void)
+{
+ uint32_t flags = 0U;
+
+#if defined(FLASH_BANK2_END)
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR_BANK2))
+#else
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR))
+#endif /* FLASH_BANK2_END */
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP;
+#if defined(FLASH_BANK2_END)
+ flags |= FLASH_FLAG_WRPERR | FLASH_FLAG_WRPERR_BANK2;
+#else
+ flags |= FLASH_FLAG_WRPERR;
+#endif /* FLASH_BANK2_END */
+ }
+#if defined(FLASH_BANK2_END)
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR_BANK2))
+#else
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
+#endif /* FLASH_BANK2_END */
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_PROG;
+#if defined(FLASH_BANK2_END)
+ flags |= FLASH_FLAG_PGERR | FLASH_FLAG_PGERR_BANK2;
+#else
+ flags |= FLASH_FLAG_PGERR;
+#endif /* FLASH_BANK2_END */
+ }
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_OPTV;
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
+ }
+
+ /* Clear FLASH error pending bits */
+ __HAL_FLASH_CLEAR_FLAG(flags);
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm32/f103c8t6/stm32f1xx_hal_flash_ex.c b/stm32/f103c8t6/stm32f1xx_hal_flash_ex.c
new file mode 100644
index 0000000..27b07b8
--- /dev/null
+++ b/stm32/f103c8t6/stm32f1xx_hal_flash_ex.c
@@ -0,0 +1,1127 @@
+/**
+ ******************************************************************************
+ * @file stm32f1xx_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 peripheral:
+ * + Extended Initialization/de-initialization functions
+ * + Extended I/O operation functions
+ * + Extended Peripheral Control functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### Flash peripheral extended features #####
+ ==============================================================================
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..] This driver provides functions to configure and program the FLASH memory
+ of all STM32F1xxx devices. It includes
+
+ (++) Set/Reset the write protection
+ (++) Program the user Option Bytes
+ (++) Get the Read protection Level
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2016 STMicroelectronics.
+ * All rights reserved.
+ *
+ * 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 "stm32f1xx_hal.h"
+
+/** @addtogroup STM32F1xx_HAL_Driver
+ * @{
+ */
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/** @addtogroup FLASH
+ * @{
+ */
+/** @addtogroup FLASH_Private_Variables
+ * @{
+ */
+/* Variables used for Erase pages under interruption*/
+extern FLASH_ProcessTypeDef pFlash;
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASHEx FLASHEx
+ * @brief FLASH HAL Extension module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup FLASHEx_Private_Constants FLASHEx Private Constants
+ * @{
+ */
+#define FLASH_POSITION_IWDGSW_BIT FLASH_OBR_IWDG_SW_Pos
+#define FLASH_POSITION_OB_USERDATA0_BIT FLASH_OBR_DATA0_Pos
+#define FLASH_POSITION_OB_USERDATA1_BIT FLASH_OBR_DATA1_Pos
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/** @defgroup FLASHEx_Private_Macros FLASHEx Private Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
+ * @{
+ */
+/* Erase operations */
+static void FLASH_MassErase(uint32_t Banks);
+void FLASH_PageErase(uint32_t PageAddress);
+
+/* Option bytes control */
+static HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WriteProtectPage);
+static HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WriteProtectPage);
+static HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t ReadProtectLevel);
+static HAL_StatusTypeDef FLASH_OB_UserConfig(uint8_t UserConfig);
+static HAL_StatusTypeDef FLASH_OB_ProgramData(uint32_t Address, uint8_t Data);
+static uint32_t FLASH_OB_GetWRP(void);
+static uint32_t FLASH_OB_GetRDP(void);
+static uint8_t FLASH_OB_GetUser(void);
+
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+/** @defgroup FLASHEx_Exported_Functions FLASHEx Exported Functions
+ * @{
+ */
+
+/** @defgroup FLASHEx_Exported_Functions_Group1 FLASHEx Memory Erasing functions
+ * @brief FLASH Memory Erasing functions
+ *
+@verbatim
+ ==============================================================================
+ ##### FLASH Erasing Programming functions #####
+ ==============================================================================
+
+ [..] The FLASH Memory Erasing functions, includes the following functions:
+ (+) @ref HAL_FLASHEx_Erase: return only when erase has been done
+ (+) @ref HAL_FLASHEx_Erase_IT: end of erase is done when @ref HAL_FLASH_EndOfOperationCallback
+ is called with parameter 0xFFFFFFFF
+
+ [..] Any operation of erase should follow these steps:
+ (#) Call the @ref HAL_FLASH_Unlock() function to enable the flash control register and
+ program memory access.
+ (#) Call the desired function to erase page.
+ (#) Call the @ref HAL_FLASH_Lock() to disable the flash program memory access
+ (recommended to protect the FLASH memory against possible unwanted operation).
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Perform a mass erase or erase the specified FLASH memory pages
+ * @note To correctly run this function, the @ref HAL_FLASH_Unlock() function
+ * must be called before.
+ * Call the @ref HAL_FLASH_Lock() to disable the flash memory access
+ * (recommended to protect the FLASH memory against possible unwanted operation)
+ * @param[in] pEraseInit pointer to an FLASH_EraseInitTypeDef structure that
+ * contains the configuration information for the erasing.
+ *
+ * @param[out] PageError pointer to variable that
+ * contains the configuration information on faulty page in case of error
+ * (0xFFFFFFFF means that all the pages have been correctly erased)
+ *
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+ uint32_t address = 0U;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
+
+ if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
+ {
+#if defined(FLASH_BANK2_END)
+ if (pEraseInit->Banks == FLASH_BANK_BOTH)
+ {
+ /* Mass Erase requested for Bank1 and Bank2 */
+ /* Wait for last operation to be completed */
+ if ((FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) && \
+ (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK))
+ {
+ /*Mass erase to be done*/
+ FLASH_MassErase(FLASH_BANK_BOTH);
+
+ /* Wait for last operation to be completed */
+ if ((FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) && \
+ (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK))
+ {
+ status = HAL_OK;
+ }
+
+ /* If the erase operation is completed, disable the MER Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_MER);
+ CLEAR_BIT(FLASH->CR2, FLASH_CR2_MER);
+ }
+ }
+ else if (pEraseInit->Banks == FLASH_BANK_2)
+ {
+ /* Mass Erase requested for Bank2 */
+ /* Wait for last operation to be completed */
+ if (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
+ {
+ /*Mass erase to be done*/
+ FLASH_MassErase(FLASH_BANK_2);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the erase operation is completed, disable the MER Bit */
+ CLEAR_BIT(FLASH->CR2, FLASH_CR2_MER);
+ }
+ }
+ else
+#endif /* FLASH_BANK2_END */
+ {
+ /* Mass Erase requested for Bank1 */
+ /* Wait for last operation to be completed */
+ if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
+ {
+ /*Mass erase to be done*/
+ FLASH_MassErase(FLASH_BANK_1);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the erase operation is completed, disable the MER Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_MER);
+ }
+ }
+ }
+ else
+ {
+ /* Page Erase is requested */
+ /* Check the parameters */
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(pEraseInit->PageAddress));
+ assert_param(IS_FLASH_NB_PAGES(pEraseInit->PageAddress, pEraseInit->NbPages));
+
+#if defined(FLASH_BANK2_END)
+ /* Page Erase requested on address located on bank2 */
+ if(pEraseInit->PageAddress > FLASH_BANK1_END)
+ {
+ /* Wait for last operation to be completed */
+ if (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
+ {
+ /*Initialization of PageError variable*/
+ *PageError = 0xFFFFFFFFU;
+
+ /* Erase by page by page to be done*/
+ for(address = pEraseInit->PageAddress;
+ address < (pEraseInit->PageAddress + (pEraseInit->NbPages)*FLASH_PAGE_SIZE);
+ address += FLASH_PAGE_SIZE)
+ {
+ FLASH_PageErase(address);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the erase operation is completed, disable the PER Bit */
+ CLEAR_BIT(FLASH->CR2, FLASH_CR2_PER);
+
+ if (status != HAL_OK)
+ {
+ /* In case of error, stop erase procedure and return the faulty address */
+ *PageError = address;
+ break;
+ }
+ }
+ }
+ }
+ else
+#endif /* FLASH_BANK2_END */
+ {
+ /* Page Erase requested on address located on bank1 */
+ /* Wait for last operation to be completed */
+ if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
+ {
+ /*Initialization of PageError variable*/
+ *PageError = 0xFFFFFFFFU;
+
+ /* Erase page by page to be done*/
+ for(address = pEraseInit->PageAddress;
+ address < ((pEraseInit->NbPages * FLASH_PAGE_SIZE) + pEraseInit->PageAddress);
+ address += FLASH_PAGE_SIZE)
+ {
+ FLASH_PageErase(address);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the erase operation is completed, disable the PER Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
+
+ if (status != HAL_OK)
+ {
+ /* In case of error, stop erase procedure and return the faulty address */
+ *PageError = address;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled
+ * @note To correctly run this function, the @ref HAL_FLASH_Unlock() function
+ * must be called before.
+ * Call the @ref HAL_FLASH_Lock() to disable the flash memory access
+ * (recommended to protect the FLASH memory against possible unwanted operation)
+ * @param pEraseInit pointer to an FLASH_EraseInitTypeDef structure that
+ * contains the configuration information for the erasing.
+ *
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* If procedure already ongoing, reject the next one */
+ if (pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
+
+ /* Enable End of FLASH Operation and Error source interrupts */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
+
+#if defined(FLASH_BANK2_END)
+ /* Enable End of FLASH Operation and Error source interrupts */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP_BANK2 | FLASH_IT_ERR_BANK2);
+
+#endif
+ if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
+ {
+ /*Mass erase to be done*/
+ pFlash.ProcedureOnGoing = FLASH_PROC_MASSERASE;
+ FLASH_MassErase(pEraseInit->Banks);
+ }
+ else
+ {
+ /* Erase by page to be done*/
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(pEraseInit->PageAddress));
+ assert_param(IS_FLASH_NB_PAGES(pEraseInit->PageAddress, pEraseInit->NbPages));
+
+ pFlash.ProcedureOnGoing = FLASH_PROC_PAGEERASE;
+ pFlash.DataRemaining = pEraseInit->NbPages;
+ pFlash.Address = pEraseInit->PageAddress;
+
+ /*Erase 1st page and wait for IT*/
+ FLASH_PageErase(pEraseInit->PageAddress);
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASHEx_Exported_Functions_Group2 Option Bytes Programming functions
+ * @brief Option Bytes Programming functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Option Bytes Programming functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the FLASH
+ option bytes operations.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Erases the FLASH option bytes.
+ * @note This functions erases all option bytes except the Read protection (RDP).
+ * The function @ref HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
+ * The function @ref HAL_FLASH_OB_Unlock() should be called before to unlock the options bytes
+ * The function @ref HAL_FLASH_OB_Launch() should be called after to force the reload of the options bytes
+ * (system reset will occur)
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_FLASHEx_OBErase(void)
+{
+ uint8_t rdptmp = OB_RDP_LEVEL_0;
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Get the actual read protection Option Byte value */
+ rdptmp = FLASH_OB_GetRDP();
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Clean the error context */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* If the previous operation is completed, proceed to erase the option bytes */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTER);
+ SET_BIT(FLASH->CR, FLASH_CR_STRT);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the erase operation is completed, disable the OPTER Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTER);
+
+ if(status == HAL_OK)
+ {
+ /* Restore the last read protection Option Byte value */
+ status = FLASH_OB_RDP_LevelConfig(rdptmp);
+ }
+ }
+
+ /* Return the erase status */
+ return status;
+}
+
+/**
+ * @brief Program option bytes
+ * @note The function @ref HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
+ * The function @ref HAL_FLASH_OB_Unlock() should be called before to unlock the options bytes
+ * The function @ref HAL_FLASH_OB_Launch() should be called after to force the reload of the options bytes
+ * (system reset will occur)
+ *
+ * @param pOBInit pointer to an FLASH_OBInitStruct structure that
+ * contains the configuration information for the programming.
+ *
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Check the parameters */
+ assert_param(IS_OPTIONBYTE(pOBInit->OptionType));
+
+ /* Write protection configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_WRP) == OPTIONBYTE_WRP)
+ {
+ assert_param(IS_WRPSTATE(pOBInit->WRPState));
+ if (pOBInit->WRPState == OB_WRPSTATE_ENABLE)
+ {
+ /* Enable of Write protection on the selected page */
+ status = FLASH_OB_EnableWRP(pOBInit->WRPPage);
+ }
+ else
+ {
+ /* Disable of Write protection on the selected page */
+ status = FLASH_OB_DisableWRP(pOBInit->WRPPage);
+ }
+ if (status != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ return status;
+ }
+ }
+
+ /* Read protection configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_RDP) == OPTIONBYTE_RDP)
+ {
+ status = FLASH_OB_RDP_LevelConfig(pOBInit->RDPLevel);
+ if (status != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ return status;
+ }
+ }
+
+ /* USER configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_USER) == OPTIONBYTE_USER)
+ {
+ status = FLASH_OB_UserConfig(pOBInit->USERConfig);
+ if (status != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ return status;
+ }
+ }
+
+ /* DATA configuration*/
+ if((pOBInit->OptionType & OPTIONBYTE_DATA) == OPTIONBYTE_DATA)
+ {
+ status = FLASH_OB_ProgramData(pOBInit->DATAAddress, pOBInit->DATAData);
+ if (status != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ return status;
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Get the Option byte configuration
+ * @param pOBInit pointer to an FLASH_OBInitStruct structure that
+ * contains the configuration information for the programming.
+ *
+ * @retval None
+ */
+void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
+{
+ pOBInit->OptionType = OPTIONBYTE_WRP | OPTIONBYTE_RDP | OPTIONBYTE_USER;
+
+ /*Get WRP*/
+ pOBInit->WRPPage = FLASH_OB_GetWRP();
+
+ /*Get RDP Level*/
+ pOBInit->RDPLevel = FLASH_OB_GetRDP();
+
+ /*Get USER*/
+ pOBInit->USERConfig = FLASH_OB_GetUser();
+}
+
+/**
+ * @brief Get the Option byte user data
+ * @param DATAAdress Address of the option byte DATA
+ * This parameter can be one of the following values:
+ * @arg @ref OB_DATA_ADDRESS_DATA0
+ * @arg @ref OB_DATA_ADDRESS_DATA1
+ * @retval Value programmed in USER data
+ */
+uint32_t HAL_FLASHEx_OBGetUserData(uint32_t DATAAdress)
+{
+ uint32_t value = 0;
+
+ if (DATAAdress == OB_DATA_ADDRESS_DATA0)
+ {
+ /* Get value programmed in OB USER Data0 */
+ value = READ_BIT(FLASH->OBR, FLASH_OBR_DATA0) >> FLASH_POSITION_OB_USERDATA0_BIT;
+ }
+ else
+ {
+ /* Get value programmed in OB USER Data1 */
+ value = READ_BIT(FLASH->OBR, FLASH_OBR_DATA1) >> FLASH_POSITION_OB_USERDATA1_BIT;
+ }
+
+ return value;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup FLASHEx_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Full erase of FLASH memory Bank
+ * @param Banks Banks to be erased
+ * This parameter can be one of the following values:
+ * @arg @ref FLASH_BANK_1 Bank1 to be erased
+ @if STM32F101xG
+ * @arg @ref FLASH_BANK_2 Bank2 to be erased
+ * @arg @ref FLASH_BANK_BOTH Bank1 and Bank2 to be erased
+ @endif
+ @if STM32F103xG
+ * @arg @ref FLASH_BANK_2 Bank2 to be erased
+ * @arg @ref FLASH_BANK_BOTH Bank1 and Bank2 to be erased
+ @endif
+ *
+ * @retval None
+ */
+static void FLASH_MassErase(uint32_t Banks)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_BANK(Banks));
+
+ /* Clean the error context */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+#if defined(FLASH_BANK2_END)
+ if(Banks == FLASH_BANK_BOTH)
+ {
+ /* bank1 & bank2 will be erased*/
+ SET_BIT(FLASH->CR, FLASH_CR_MER);
+ SET_BIT(FLASH->CR2, FLASH_CR2_MER);
+ SET_BIT(FLASH->CR, FLASH_CR_STRT);
+ SET_BIT(FLASH->CR2, FLASH_CR2_STRT);
+ }
+ else if(Banks == FLASH_BANK_2)
+ {
+ /*Only bank2 will be erased*/
+ SET_BIT(FLASH->CR2, FLASH_CR2_MER);
+ SET_BIT(FLASH->CR2, FLASH_CR2_STRT);
+ }
+ else
+ {
+#endif /* FLASH_BANK2_END */
+#if !defined(FLASH_BANK2_END)
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Banks);
+#endif /* FLASH_BANK2_END */
+ /* Only bank1 will be erased*/
+ SET_BIT(FLASH->CR, FLASH_CR_MER);
+ SET_BIT(FLASH->CR, FLASH_CR_STRT);
+#if defined(FLASH_BANK2_END)
+ }
+#endif /* FLASH_BANK2_END */
+}
+
+/**
+ * @brief Enable the write protection of the desired pages
+ * @note An option byte erase is done automatically in this function.
+ * @note When the memory read protection level is selected (RDP level = 1),
+ * it is not possible to program or erase the flash page i if
+ * debug features are connected or boot code is executed in RAM, even if nWRPi = 1
+ *
+ * @param WriteProtectPage specifies the page(s) to be write protected.
+ * The value of this parameter depend on device used within the same series
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WriteProtectPage)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint16_t WRP0_Data = 0xFFFF;
+#if defined(FLASH_WRP1_WRP1)
+ uint16_t WRP1_Data = 0xFFFF;
+#endif /* FLASH_WRP1_WRP1 */
+#if defined(FLASH_WRP2_WRP2)
+ uint16_t WRP2_Data = 0xFFFF;
+#endif /* FLASH_WRP2_WRP2 */
+#if defined(FLASH_WRP3_WRP3)
+ uint16_t WRP3_Data = 0xFFFF;
+#endif /* FLASH_WRP3_WRP3 */
+
+ /* Check the parameters */
+ assert_param(IS_OB_WRP(WriteProtectPage));
+
+ /* Get current write protected pages and the new pages to be protected ******/
+ WriteProtectPage = (uint32_t)(~((~FLASH_OB_GetWRP()) | WriteProtectPage));
+
+#if defined(OB_WRP_PAGES0TO15MASK)
+ WRP0_Data = (uint16_t)(WriteProtectPage & OB_WRP_PAGES0TO15MASK);
+#elif defined(OB_WRP_PAGES0TO31MASK)
+ WRP0_Data = (uint16_t)(WriteProtectPage & OB_WRP_PAGES0TO31MASK);
+#endif /* OB_WRP_PAGES0TO31MASK */
+
+#if defined(OB_WRP_PAGES16TO31MASK)
+ WRP1_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES16TO31MASK) >> 8U);
+#elif defined(OB_WRP_PAGES32TO63MASK)
+ WRP1_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES32TO63MASK) >> 8U);
+#endif /* OB_WRP_PAGES32TO63MASK */
+
+#if defined(OB_WRP_PAGES64TO95MASK)
+ WRP2_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES64TO95MASK) >> 16U);
+#endif /* OB_WRP_PAGES64TO95MASK */
+#if defined(OB_WRP_PAGES32TO47MASK)
+ WRP2_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES32TO47MASK) >> 16U);
+#endif /* OB_WRP_PAGES32TO47MASK */
+
+#if defined(OB_WRP_PAGES96TO127MASK)
+ WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES96TO127MASK) >> 24U);
+#elif defined(OB_WRP_PAGES48TO255MASK)
+ WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO255MASK) >> 24U);
+#elif defined(OB_WRP_PAGES48TO511MASK)
+ WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO511MASK) >> 24U);
+#elif defined(OB_WRP_PAGES48TO127MASK)
+ WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO127MASK) >> 24U);
+#endif /* OB_WRP_PAGES96TO127MASK */
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Clean the error context */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* To be able to write again option byte, need to perform a option byte erase */
+ status = HAL_FLASHEx_OBErase();
+ if (status == HAL_OK)
+ {
+ /* Enable write protection */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
+
+#if defined(FLASH_WRP0_WRP0)
+ if(WRP0_Data != 0xFFU)
+ {
+ OB->WRP0 &= WRP0_Data;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+ }
+#endif /* FLASH_WRP0_WRP0 */
+
+#if defined(FLASH_WRP1_WRP1)
+ if((status == HAL_OK) && (WRP1_Data != 0xFFU))
+ {
+ OB->WRP1 &= WRP1_Data;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+ }
+#endif /* FLASH_WRP1_WRP1 */
+
+#if defined(FLASH_WRP2_WRP2)
+ if((status == HAL_OK) && (WRP2_Data != 0xFFU))
+ {
+ OB->WRP2 &= WRP2_Data;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+ }
+#endif /* FLASH_WRP2_WRP2 */
+
+#if defined(FLASH_WRP3_WRP3)
+ if((status == HAL_OK) && (WRP3_Data != 0xFFU))
+ {
+ OB->WRP3 &= WRP3_Data;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+ }
+#endif /* FLASH_WRP3_WRP3 */
+
+ /* if the program operation is completed, disable the OPTPG Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Disable the write protection of the desired pages
+ * @note An option byte erase is done automatically in this function.
+ * @note When the memory read protection level is selected (RDP level = 1),
+ * it is not possible to program or erase the flash page i if
+ * debug features are connected or boot code is executed in RAM, even if nWRPi = 1
+ *
+ * @param WriteProtectPage specifies the page(s) to be write unprotected.
+ * The value of this parameter depend on device used within the same series
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WriteProtectPage)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint16_t WRP0_Data = 0xFFFF;
+#if defined(FLASH_WRP1_WRP1)
+ uint16_t WRP1_Data = 0xFFFF;
+#endif /* FLASH_WRP1_WRP1 */
+#if defined(FLASH_WRP2_WRP2)
+ uint16_t WRP2_Data = 0xFFFF;
+#endif /* FLASH_WRP2_WRP2 */
+#if defined(FLASH_WRP3_WRP3)
+ uint16_t WRP3_Data = 0xFFFF;
+#endif /* FLASH_WRP3_WRP3 */
+
+ /* Check the parameters */
+ assert_param(IS_OB_WRP(WriteProtectPage));
+
+ /* Get current write protected pages and the new pages to be unprotected ******/
+ WriteProtectPage = (FLASH_OB_GetWRP() | WriteProtectPage);
+
+#if defined(OB_WRP_PAGES0TO15MASK)
+ WRP0_Data = (uint16_t)(WriteProtectPage & OB_WRP_PAGES0TO15MASK);
+#elif defined(OB_WRP_PAGES0TO31MASK)
+ WRP0_Data = (uint16_t)(WriteProtectPage & OB_WRP_PAGES0TO31MASK);
+#endif /* OB_WRP_PAGES0TO31MASK */
+
+#if defined(OB_WRP_PAGES16TO31MASK)
+ WRP1_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES16TO31MASK) >> 8U);
+#elif defined(OB_WRP_PAGES32TO63MASK)
+ WRP1_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES32TO63MASK) >> 8U);
+#endif /* OB_WRP_PAGES32TO63MASK */
+
+#if defined(OB_WRP_PAGES64TO95MASK)
+ WRP2_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES64TO95MASK) >> 16U);
+#endif /* OB_WRP_PAGES64TO95MASK */
+#if defined(OB_WRP_PAGES32TO47MASK)
+ WRP2_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES32TO47MASK) >> 16U);
+#endif /* OB_WRP_PAGES32TO47MASK */
+
+#if defined(OB_WRP_PAGES96TO127MASK)
+ WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES96TO127MASK) >> 24U);
+#elif defined(OB_WRP_PAGES48TO255MASK)
+ WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO255MASK) >> 24U);
+#elif defined(OB_WRP_PAGES48TO511MASK)
+ WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO511MASK) >> 24U);
+#elif defined(OB_WRP_PAGES48TO127MASK)
+ WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO127MASK) >> 24U);
+#endif /* OB_WRP_PAGES96TO127MASK */
+
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Clean the error context */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* To be able to write again option byte, need to perform a option byte erase */
+ status = HAL_FLASHEx_OBErase();
+ if (status == HAL_OK)
+ {
+ SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
+
+#if defined(FLASH_WRP0_WRP0)
+ if(WRP0_Data != 0xFFU)
+ {
+ OB->WRP0 |= WRP0_Data;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+ }
+#endif /* FLASH_WRP0_WRP0 */
+
+#if defined(FLASH_WRP1_WRP1)
+ if((status == HAL_OK) && (WRP1_Data != 0xFFU))
+ {
+ OB->WRP1 |= WRP1_Data;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+ }
+#endif /* FLASH_WRP1_WRP1 */
+
+#if defined(FLASH_WRP2_WRP2)
+ if((status == HAL_OK) && (WRP2_Data != 0xFFU))
+ {
+ OB->WRP2 |= WRP2_Data;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+ }
+#endif /* FLASH_WRP2_WRP2 */
+
+#if defined(FLASH_WRP3_WRP3)
+ if((status == HAL_OK) && (WRP3_Data != 0xFFU))
+ {
+ OB->WRP3 |= WRP3_Data;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+ }
+#endif /* FLASH_WRP3_WRP3 */
+
+ /* if the program operation is completed, disable the OPTPG Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Set the read protection level.
+ * @param ReadProtectLevel specifies the read protection level.
+ * This parameter can be one of the following values:
+ * @arg @ref OB_RDP_LEVEL_0 No protection
+ * @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t ReadProtectLevel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_RDP_LEVEL(ReadProtectLevel));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Clean the error context */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* If the previous operation is completed, proceed to erase the option bytes */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTER);
+ SET_BIT(FLASH->CR, FLASH_CR_STRT);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the erase operation is completed, disable the OPTER Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTER);
+
+ if(status == HAL_OK)
+ {
+ /* Enable the Option Bytes Programming operation */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
+
+ WRITE_REG(OB->RDP, ReadProtectLevel);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* if the program operation is completed, disable the OPTPG Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Program the FLASH User Option Byte.
+ * @note Programming of the OB should be performed only after an erase (otherwise PGERR occurs)
+ * @param UserConfig The FLASH User Option Bytes values FLASH_OBR_IWDG_SW(Bit2),
+ * FLASH_OBR_nRST_STOP(Bit3),FLASH_OBR_nRST_STDBY(Bit4).
+ * And BFBF2(Bit5) for STM32F101xG and STM32F103xG .
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef FLASH_OB_UserConfig(uint8_t UserConfig)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_IWDG_SOURCE((UserConfig&OB_IWDG_SW)));
+ assert_param(IS_OB_STOP_SOURCE((UserConfig&OB_STOP_NO_RST)));
+ assert_param(IS_OB_STDBY_SOURCE((UserConfig&OB_STDBY_NO_RST)));
+#if defined(FLASH_BANK2_END)
+ assert_param(IS_OB_BOOT1((UserConfig&OB_BOOT1_SET)));
+#endif /* FLASH_BANK2_END */
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Clean the error context */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Enable the Option Bytes Programming operation */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
+
+#if defined(FLASH_BANK2_END)
+ OB->USER = (UserConfig | 0xF0U);
+#else
+ OB->USER = (UserConfig | 0x88U);
+#endif /* FLASH_BANK2_END */
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* if the program operation is completed, disable the OPTPG Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Programs a half word at a specified Option Byte Data address.
+ * @note The function @ref HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
+ * The function @ref HAL_FLASH_OB_Unlock() should be called before to unlock the options bytes
+ * The function @ref HAL_FLASH_OB_Launch() should be called after to force the reload of the options bytes
+ * (system reset will occur)
+ * Programming of the OB should be performed only after an erase (otherwise PGERR occurs)
+ * @param Address specifies the address to be programmed.
+ * This parameter can be 0x1FFFF804 or 0x1FFFF806.
+ * @param Data specifies the data to be programmed.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef FLASH_OB_ProgramData(uint32_t Address, uint8_t Data)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_OB_DATA_ADDRESS(Address));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Clean the error context */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Enables the Option Bytes Programming operation */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
+ *(__IO uint16_t*)Address = Data;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the program operation is completed, disable the OPTPG Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
+ }
+ /* Return the Option Byte Data Program Status */
+ return status;
+}
+
+/**
+ * @brief Return the FLASH Write Protection Option Bytes value.
+ * @retval The FLASH Write Protection Option Bytes value
+ */
+static uint32_t FLASH_OB_GetWRP(void)
+{
+ /* Return the FLASH write protection Register value */
+ return (uint32_t)(READ_REG(FLASH->WRPR));
+}
+
+/**
+ * @brief Returns the FLASH Read Protection level.
+ * @retval FLASH RDP level
+ * This parameter can be one of the following values:
+ * @arg @ref OB_RDP_LEVEL_0 No protection
+ * @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
+ */
+static uint32_t FLASH_OB_GetRDP(void)
+{
+ uint32_t readstatus = OB_RDP_LEVEL_0;
+ uint32_t tmp_reg = 0U;
+
+ /* Read RDP level bits */
+ tmp_reg = READ_BIT(FLASH->OBR, FLASH_OBR_RDPRT);
+
+ if (tmp_reg == FLASH_OBR_RDPRT)
+ {
+ readstatus = OB_RDP_LEVEL_1;
+ }
+ else
+ {
+ readstatus = OB_RDP_LEVEL_0;
+ }
+
+ return readstatus;
+}
+
+/**
+ * @brief Return the FLASH User Option Byte value.
+ * @retval The FLASH User Option Bytes values: FLASH_OBR_IWDG_SW(Bit2),
+ * FLASH_OBR_nRST_STOP(Bit3),FLASH_OBR_nRST_STDBY(Bit4).
+ * And FLASH_OBR_BFB2(Bit5) for STM32F101xG and STM32F103xG .
+ */
+static uint8_t FLASH_OB_GetUser(void)
+{
+ /* Return the User Option Byte */
+ return (uint8_t)((READ_REG(FLASH->OBR) & FLASH_OBR_USER) >> FLASH_POSITION_IWDGSW_BIT);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup FLASH
+ * @{
+ */
+
+/** @addtogroup FLASH_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Erase the specified FLASH memory page
+ * @param PageAddress FLASH page to erase
+ * The value of this parameter depend on device used within the same series
+ *
+ * @retval None
+ */
+void FLASH_PageErase(uint32_t PageAddress)
+{
+ /* Clean the error context */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+#if defined(FLASH_BANK2_END)
+ if(PageAddress > FLASH_BANK1_END)
+ {
+ /* Proceed to erase the page */
+ SET_BIT(FLASH->CR2, FLASH_CR2_PER);
+ WRITE_REG(FLASH->AR2, PageAddress);
+ SET_BIT(FLASH->CR2, FLASH_CR2_STRT);
+ }
+ else
+ {
+#endif /* FLASH_BANK2_END */
+ /* Proceed to erase the page */
+ SET_BIT(FLASH->CR, FLASH_CR_PER);
+ WRITE_REG(FLASH->AR, PageAddress);
+ SET_BIT(FLASH->CR, FLASH_CR_STRT);
+#if defined(FLASH_BANK2_END)
+ }
+#endif /* FLASH_BANK2_END */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm32/usb/usbd_customhid.h b/stm32/usb/usbd_customhid.h
deleted file mode 100644
index 59772a8..0000000
--- a/stm32/usb/usbd_customhid.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/**
- ******************************************************************************
- * @file usbd_customhid.h
- * @author MCD Application Team
- * @brief header file for the usbd_customhid.c file.
- ******************************************************************************
- * @attention
- *
- * © Copyright (c) 2015 STMicroelectronics.
- * All rights reserved.
- *
- * This software component is licensed by ST under Ultimate Liberty license
- * SLA0044, the "License"; You may not use this file except in compliance with
- * the License. You may obtain a copy of the License at:
- * www.st.com/SLA0044
- *
- ******************************************************************************
- */
-
-/* Define to prevent recursive inclusion -------------------------------------*/
-#ifndef __USB_CUSTOMHID_H
-#define __USB_CUSTOMHID_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Includes ------------------------------------------------------------------*/
-#include "usbd_ioreq.h"
-
-/** @addtogroup STM32_USB_DEVICE_LIBRARY
- * @{
- */
-
-/** @defgroup USBD_CUSTOM_HID
- * @brief This file is the Header file for USBD_customhid.c
- * @{
- */
-
-
-/** @defgroup USBD_CUSTOM_HID_Exported_Defines
- * @{
- */
-#define CUSTOM_HID_EPIN_ADDR 0x81U
-#define CUSTOM_HID_EPIN_SIZE 0x02U
-
-#define CUSTOM_HID_EPOUT_ADDR 0x01U
-#define CUSTOM_HID_EPOUT_SIZE 0x02U
-
-#define USB_CUSTOM_HID_CONFIG_DESC_SIZ 41U
-#define USB_CUSTOM_HID_DESC_SIZ 9U
-
-#ifndef CUSTOM_HID_HS_BINTERVAL
-#define CUSTOM_HID_HS_BINTERVAL 0x05U
-#endif /* CUSTOM_HID_HS_BINTERVAL */
-
-#ifndef CUSTOM_HID_FS_BINTERVAL
-#define CUSTOM_HID_FS_BINTERVAL 0x05U
-#endif /* CUSTOM_HID_FS_BINTERVAL */
-
-#ifndef USBD_CUSTOMHID_OUTREPORT_BUF_SIZE
-#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 0x02U
-#endif /* USBD_CUSTOMHID_OUTREPORT_BUF_SIZE */
-#ifndef USBD_CUSTOM_HID_REPORT_DESC_SIZE
-#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 163U
-#endif /* USBD_CUSTOM_HID_REPORT_DESC_SIZE */
-
-#define CUSTOM_HID_DESCRIPTOR_TYPE 0x21U
-#define CUSTOM_HID_REPORT_DESC 0x22U
-
-#define CUSTOM_HID_REQ_SET_PROTOCOL 0x0BU
-#define CUSTOM_HID_REQ_GET_PROTOCOL 0x03U
-
-#define CUSTOM_HID_REQ_SET_IDLE 0x0AU
-#define CUSTOM_HID_REQ_GET_IDLE 0x02U
-
-#define CUSTOM_HID_REQ_SET_REPORT 0x09U
-#define CUSTOM_HID_REQ_GET_REPORT 0x01U
-/**
- * @}
- */
-
-
-/** @defgroup USBD_CORE_Exported_TypesDefinitions
- * @{
- */
-typedef enum
-{
- CUSTOM_HID_IDLE = 0U,
- CUSTOM_HID_BUSY,
-}
-CUSTOM_HID_StateTypeDef;
-
-typedef struct _USBD_CUSTOM_HID_Itf
-{
- uint8_t *pReport;
- uint16_t pReportLen;
- int8_t (* Init)(void);
- int8_t (* DeInit)(void);
- int8_t (* OutEvent)(uint8_t event_idx, uint8_t state);
-
-} USBD_CUSTOM_HID_ItfTypeDef;
-
-typedef struct
-{
- uint8_t Report_buf[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE];
- uint32_t Protocol;
- uint32_t IdleState;
- uint32_t AltSetting;
- uint32_t IsReportAvailable;
- CUSTOM_HID_StateTypeDef state;
-}
-USBD_CUSTOM_HID_HandleTypeDef;
-/**
- * @}
- */
-
-
-
-/** @defgroup USBD_CORE_Exported_Macros
- * @{
- */
-
-/**
- * @}
- */
-
-/** @defgroup USBD_CORE_Exported_Variables
- * @{
- */
-
-extern USBD_ClassTypeDef USBD_CUSTOM_HID;
-#define USBD_CUSTOM_HID_CLASS &USBD_CUSTOM_HID
-/**
- * @}
- */
-
-/** @defgroup USB_CORE_Exported_Functions
- * @{
- */
-uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev,
- uint8_t *report,
- uint16_t len);
-
-
-
-uint8_t USBD_CUSTOM_HID_RegisterInterface(USBD_HandleTypeDef *pdev,
- USBD_CUSTOM_HID_ItfTypeDef *fops);
-
-/**
- * @}
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __USB_CUSTOMHID_H */
-/**
- * @}
- */
-
-/**
- * @}
- */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/