Changeset - a477ff27aff8
Software/hoverboard-firmware-hack_modified20190825/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
Show inline comments
 
new file 100644
 
/**
 
  ******************************************************************************
 
  * @file    stm32f1xx_hal.c
 
  * @author  MCD Application Team
 
  * @version V1.1.1
 
  * @date    12-May-2017
 
  * @brief   HAL module driver.
 
  *          This is the common part of the HAL initialization
 
  *
 
  @verbatim
 
  ==============================================================================
 
                     ##### How to use this driver #####
 
  ==============================================================================
 
    [..]
 
    The common HAL driver contains a set of generic and common APIs that can be
 
    used by the PPP peripheral drivers and the user to start using the HAL. 
 
    [..]
 
    The HAL contains two APIs' categories: 
 
         (+) Common HAL APIs
 
         (+) Services HAL APIs
 

	
 
  @endverbatim
 
  ******************************************************************************
 
  * @attention
 
  *
 
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
 
  *
 
  * Redistribution and use in source and binary forms, with or without modification,
 
  * are permitted provided that the following conditions are met:
 
  *   1. Redistributions of source code must retain the above copyright notice,
 
  *      this list of conditions and the following disclaimer.
 
  *   2. Redistributions in binary form must reproduce the above copyright notice,
 
  *      this list of conditions and the following disclaimer in the documentation
 
  *      and/or other materials provided with the distribution.
 
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
 
  *      may be used to endorse or promote products derived from this software
 
  *      without specific prior written permission.
 
  *
 
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  *
 
  ******************************************************************************
 
  */
 

	
 
/* Includes ------------------------------------------------------------------*/
 
#include "stm32f1xx_hal.h"
 

	
 
/** @addtogroup STM32F1xx_HAL_Driver
 
  * @{
 
  */
 

	
 
/** @defgroup HAL HAL
 
  * @brief HAL module driver.
 
  * @{
 
  */
 

	
 
#ifdef HAL_MODULE_ENABLED
 

	
 
/* Private typedef -----------------------------------------------------------*/
 
/* Private define ------------------------------------------------------------*/
 

	
 
/** @defgroup HAL_Private_Constants HAL Private Constants
 
  * @{
 
  */
 
/**
 
 * @brief STM32F1xx HAL Driver version number V1.1.1
 
   */
 
#define __STM32F1xx_HAL_VERSION_MAIN   (0x01U) /*!< [31:24] main version */
 
#define __STM32F1xx_HAL_VERSION_SUB1   (0x01U) /*!< [23:16] sub1 version */
 
#define __STM32F1xx_HAL_VERSION_SUB2   (0x01U) /*!< [15:8]  sub2 version */
 
#define __STM32F1xx_HAL_VERSION_RC     (0x00U) /*!< [7:0]  release candidate */
 
#define __STM32F1xx_HAL_VERSION         ((__STM32F1xx_HAL_VERSION_MAIN << 24)\
 
                                        |(__STM32F1xx_HAL_VERSION_SUB1 << 16)\
 
                                        |(__STM32F1xx_HAL_VERSION_SUB2 << 8 )\
 
                                        |(__STM32F1xx_HAL_VERSION_RC))
 

	
 
#define IDCODE_DEVID_MASK    0x00000FFFU
 

	
 
/**
 
  * @}
 
  */
 

	
 
/* Private macro -------------------------------------------------------------*/
 
/* Private variables ---------------------------------------------------------*/
 

	
 
/** @defgroup HAL_Private_Variables HAL Private Variables
 
  * @{
 
  */
 
__IO uint32_t uwTick;
 
/**
 
  * @}
 
  */
 
/* Private function prototypes -----------------------------------------------*/
 
/* Exported functions ---------------------------------------------------------*/
 

	
 
/** @defgroup HAL_Exported_Functions HAL Exported Functions
 
  * @{
 
  */
 

	
 
/** @defgroup HAL_Exported_Functions_Group1 Initialization and de-initialization Functions 
 
 *  @brief    Initialization and de-initialization functions
 
 *
 
@verbatim
 
 ===============================================================================
 
              ##### Initialization and de-initialization functions #####
 
 ===============================================================================
 
   [..]  This section provides functions allowing to:
 
      (+) Initializes the Flash interface, the NVIC allocation and initial clock 
 
          configuration. It initializes the source of time base also when timeout 
 
          is needed and the backup domain when enabled.
 
      (+) de-Initializes common part of the HAL.
 
      (+) Configure The time base source to have 1ms time base with a dedicated 
 
          Tick interrupt priority. 
 
        (++) Systick timer is used by default as source of time base, but user 
 
             can eventually implement his proper time base source (a general purpose 
 
             timer for example or other time source), keeping in mind that Time base 
 
             duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and 
 
             handled in milliseconds basis.
 
        (++) Time base configuration function (HAL_InitTick ()) is called automatically 
 
             at the beginning of the program after reset by HAL_Init() or at any time 
 
             when clock is configured, by HAL_RCC_ClockConfig(). 
 
        (++) Source of time base is configured  to generate interrupts at regular 
 
             time intervals. Care must be taken if HAL_Delay() is called from a 
 
             peripheral ISR process, the Tick interrupt line must have higher priority 
 
            (numerically lower) than the peripheral interrupt. Otherwise the caller 
 
            ISR process will be blocked. 
 
       (++) functions affecting time base configurations are declared as __weak  
 
             to make  override possible  in case of other  implementations in user file.
 
@endverbatim
 
  * @{
 
  */
 

	
 
/**
 
  * @brief  This function is used to initialize the HAL Library; it must be the first 
 
  *         instruction to be executed in the main program (before to call any other
 
  *         HAL function), it performs the following:
 
  *           Configure the Flash prefetch.
 
  *           Configures the SysTick to generate an interrupt each 1 millisecond,
 
  *           which is clocked by the HSI (at this stage, the clock is not yet
 
  *           configured and thus the system is running from the internal HSI at 16 MHz).
 
  *           Set NVIC Group Priority to 4.
 
  *           Calls the HAL_MspInit() callback function defined in user file 
 
  *           "stm32f1xx_hal_msp.c" to do the global low level hardware initialization 
 
  *            
 
  * @note   SysTick is used as time base for the HAL_Delay() function, the application
 
  *         need to ensure that the SysTick time base is always set to 1 millisecond
 
  *         to have correct HAL operation.
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_Init(void)
 
{
 
  /* Configure Flash prefetch */
 
#if (PREFETCH_ENABLE != 0)
 
#if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
 
    defined(STM32F102x6) || defined(STM32F102xB) || \
 
    defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
 
    defined(STM32F105xC) || defined(STM32F107xC)
 

	
 
  /* Prefetch buffer is not available on value line devices */
 
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
 
#endif
 
#endif /* PREFETCH_ENABLE */
 

	
 
  /* Set Interrupt Group Priority */
 
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
 

	
 
  /* Use systick as time base source and configure 1ms tick (default clock after Reset is MSI) */
 
  HAL_InitTick(TICK_INT_PRIORITY);
 

	
 
  /* Init the low level hardware */
 
  HAL_MspInit();
 

	
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief This function de-Initializes common part of the HAL and stops the source
 
  *        of time base.
 
  * @note This function is optional.
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_DeInit(void)
 
{
 
  /* Reset of all peripherals */
 
  __HAL_RCC_APB1_FORCE_RESET();
 
  __HAL_RCC_APB1_RELEASE_RESET();
 

	
 
  __HAL_RCC_APB2_FORCE_RESET();
 
  __HAL_RCC_APB2_RELEASE_RESET();
 

	
 
#if defined(STM32F105xC) || defined(STM32F107xC)
 
  __HAL_RCC_AHB_FORCE_RESET();
 
  __HAL_RCC_AHB_RELEASE_RESET();
 
#endif
 
  
 
  /* De-Init the low level hardware */
 
  HAL_MspDeInit();
 
    
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief  Initializes the MSP.
 
  * @retval None
 
  */
 
__weak void HAL_MspInit(void)
 
{
 
  /* NOTE : This function Should not be modified, when the callback is needed,
 
            the HAL_MspInit could be implemented in the user file
 
   */
 
}
 

	
 
/**
 
  * @brief  DeInitializes the MSP.
 
  * @retval None
 
  */
 
__weak void HAL_MspDeInit(void)
 
{
 
  /* NOTE : This function Should not be modified, when the callback is needed,
 
            the HAL_MspDeInit could be implemented in the user file
 
   */
 
}
 

	
 
/**
 
  * @brief This function configures the source of the time base. 
 
  *        The time source is configured  to have 1ms time base with a dedicated 
 
  *        Tick interrupt priority.
 
  * @note This function is called  automatically at the beginning of program after
 
  *       reset by HAL_Init() or at any time when clock is reconfigured  by HAL_RCC_ClockConfig(). 
 
  * @note In the default implementation, SysTick timer is the source of time base. 
 
  *       It is used to generate interrupts at regular time intervals. 
 
  *       Care must be taken if HAL_Delay() is called from a peripheral ISR process, 
 
  *       The the SysTick interrupt must have higher priority (numerically lower) 
 
  *       than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
 
  *       The function is declared as __weak  to be overwritten  in case of other
 
  *       implementation  in user file.
 
  * @param TickPriority: Tick interrupt priority.
 
  * @retval HAL status
 
  */
 
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
 
{
 
  /*Configure the SysTick to have interrupt in 1ms time basis*/
 
  HAL_SYSTICK_Config(SystemCoreClock/1000U);
 

	
 
  /*Configure the SysTick IRQ priority */
 
  HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0U);
 

	
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @}
 
  */
 

	
 
/** @defgroup HAL_Exported_Functions_Group2 HAL Control functions 
 
  *  @brief    HAL Control functions
 
  *
 
@verbatim
 
 ===============================================================================
 
                      ##### HAL Control functions #####
 
 ===============================================================================
 
    [..]  This section provides functions allowing to:
 
      (+) Provide a tick value in millisecond
 
      (+) Provide a blocking delay in millisecond
 
      (+) Suspend the time base source interrupt
 
      (+) Resume the time base source interrupt
 
      (+) Get the HAL API driver version
 
      (+) Get the device identifier
 
      (+) Get the device revision identifier
 
      (+) Enable/Disable Debug module during SLEEP mode
 
      (+) Enable/Disable Debug module during STOP mode
 
      (+) Enable/Disable Debug module during STANDBY mode
 

	
 
@endverbatim
 
  * @{
 
  */
 

	
 
/**
 
  * @brief This function is called to increment  a global variable "uwTick"
 
  *        used as application time base.
 
  * @note In the default implementation, this variable is incremented each 1ms
 
  *       in Systick ISR.
 
  * @note This function is declared as __weak to be overwritten in case of other 
 
  *      implementations in user file.
 
  * @retval None
 
  */
 
__weak void HAL_IncTick(void)
 
{
 
  uwTick++;
 
}
 

	
 
/**
 
  * @brief Provides a tick value in millisecond.
 
  * @note  This function is declared as __weak  to be overwritten  in case of other 
 
  *       implementations in user file.
 
  * @retval tick value
 
  */
 
__weak uint32_t HAL_GetTick(void)
 
{
 
  return uwTick;
 
}
 

	
 
/**
 
  * @brief This function provides minimum delay (in milliseconds) based 
 
  *        on variable incremented.
 
  * @note In the default implementation , SysTick timer is the source of time base.
 
  *       It is used to generate interrupts at regular time intervals where uwTick
 
  *       is incremented.
 
  * @note This function is declared as __weak to be overwritten in case of other
 
  *       implementations in user file.
 
  * @param Delay: specifies the delay time length, in milliseconds.
 
  * @retval None
 
  */
 
__weak void HAL_Delay(__IO uint32_t Delay)
 
{
 
  uint32_t tickstart = HAL_GetTick();
 
  uint32_t wait = Delay;
 
  
 
  /* Add a period to guarantee minimum wait */
 
  if (wait < HAL_MAX_DELAY)
 
  {
 
     wait++;
 
  }
 
  
 
  while((HAL_GetTick() - tickstart) < wait)
 
  {
 
  }
 
}
 

	
 
/**
 
  * @brief Suspend Tick increment.
 
  * @note In the default implementation , SysTick timer is the source of time base. It is
 
  *       used to generate interrupts at regular time intervals. Once HAL_SuspendTick()
 
  *       is called, the SysTick interrupt will be disabled and so Tick increment 
 
  *       is suspended.
 
  * @note This function is declared as __weak to be overwritten in case of other
 
  *       implementations in user file.
 
  * @retval None
 
  */
 
__weak void HAL_SuspendTick(void)
 
{
 
  /* Disable SysTick Interrupt */
 
  CLEAR_BIT(SysTick->CTRL,SysTick_CTRL_TICKINT_Msk);
 
}
 

	
 
/**
 
  * @brief Resume Tick increment.
 
  * @note In the default implementation , SysTick timer is the source of time base. It is
 
  *       used to generate interrupts at regular time intervals. Once HAL_ResumeTick()
 
  *       is called, the SysTick interrupt will be enabled and so Tick increment 
 
  *       is resumed.
 
  * @note This function is declared as __weak to be overwritten in case of other
 
  *       implementations in user file.
 
  * @retval None
 
  */
 
__weak void HAL_ResumeTick(void)
 
{
 
  /* Enable SysTick Interrupt */
 
  SET_BIT(SysTick->CTRL,SysTick_CTRL_TICKINT_Msk);
 
}
 

	
 
/**
 
  * @brief  Returns the HAL revision
 
  * @retval version : 0xXYZR (8bits for each decimal, R for RC)
 
  */
 
uint32_t HAL_GetHalVersion(void)
 
{
 
 return __STM32F1xx_HAL_VERSION;
 
}
 

	
 
/**
 
  * @brief Returns the device revision identifier.
 
  * Note: On devices STM32F10xx8 and STM32F10xxB,
 
  *                  STM32F101xC/D/E and STM32F103xC/D/E,
 
  *                  STM32F101xF/G and STM32F103xF/G
 
  *                  STM32F10xx4 and STM32F10xx6
 
  *       Debug registers DBGMCU_IDCODE and DBGMCU_CR are accessible only in 
 
  *       debug mode (not accessible by the user software in normal mode).
 
  *       Refer to errata sheet of these devices for more details.
 
  * @retval Device revision identifier
 
  */
 
uint32_t HAL_GetREVID(void)
 
{
 
  return((DBGMCU->IDCODE) >> DBGMCU_IDCODE_REV_ID_Pos);
 
}
 

	
 
/**
 
  * @brief  Returns the device identifier.
 
  * Note: On devices STM32F10xx8 and STM32F10xxB,
 
  *                  STM32F101xC/D/E and STM32F103xC/D/E,
 
  *                  STM32F101xF/G and STM32F103xF/G
 
  *                  STM32F10xx4 and STM32F10xx6
 
  *       Debug registers DBGMCU_IDCODE and DBGMCU_CR are accessible only in 
 
  *       debug mode (not accessible by the user software in normal mode).
 
  *       Refer to errata sheet of these devices for more details.
 
  * @retval Device identifier
 
  */
 
uint32_t HAL_GetDEVID(void)
 
{
 
   return((DBGMCU->IDCODE) & IDCODE_DEVID_MASK);
 
}
 

	
 
/**
 
  * @brief  Enable the Debug Module during SLEEP mode
 
  * @retval None
 
  */
 
void HAL_DBGMCU_EnableDBGSleepMode(void)
 
{
 
  SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
 
}
 

	
 
/**
 
  * @brief  Disable the Debug Module during SLEEP mode
 
  * Note: On devices STM32F10xx8 and STM32F10xxB,
 
  *                  STM32F101xC/D/E and STM32F103xC/D/E,
 
  *                  STM32F101xF/G and STM32F103xF/G
 
  *                  STM32F10xx4 and STM32F10xx6
 
  *       Debug registers DBGMCU_IDCODE and DBGMCU_CR are accessible only in 
 
  *       debug mode (not accessible by the user software in normal mode).
 
  *       Refer to errata sheet of these devices for more details.
 
  * @retval None
 
  */
 
void HAL_DBGMCU_DisableDBGSleepMode(void)
 
{
 
  CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
 
}
 

	
 
/**
 
  * @brief  Enable the Debug Module during STOP mode
 
  * Note: On devices STM32F10xx8 and STM32F10xxB,
 
  *                  STM32F101xC/D/E and STM32F103xC/D/E,
 
  *                  STM32F101xF/G and STM32F103xF/G
 
  *                  STM32F10xx4 and STM32F10xx6
 
  *       Debug registers DBGMCU_IDCODE and DBGMCU_CR are accessible only in 
 
  *       debug mode (not accessible by the user software in normal mode).
 
  *       Refer to errata sheet of these devices for more details.
 
  * Note: On all STM32F1 devices:
 
  *       If the system tick timer interrupt is enabled during the Stop mode 
 
  *       debug (DBG_STOP bit set in the DBGMCU_CR register ), it will wakeup
 
  *       the system from Stop mode.
 
  *       Workaround: To debug the Stop mode, disable the system tick timer 
 
  *       interrupt.
 
  *       Refer to errata sheet of these devices for more details.
 
  * Note: On all STM32F1 devices:
 
  *       If the system tick timer interrupt is enabled during the Stop mode  
 
  *       debug (DBG_STOP bit set in the DBGMCU_CR register ), it will wakeup
 
  *       the system from Stop mode.
 
  *       Workaround: To debug the Stop mode, disable the system tick timer
 
  *       interrupt.
 
  *       Refer to errata sheet of these devices for more details.
 
  * @retval None
 
  */
 
void HAL_DBGMCU_EnableDBGStopMode(void)
 
{
 
  SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
 
}
 

	
 
/**
 
  * @brief  Disable the Debug Module during STOP mode
 
  * Note: On devices STM32F10xx8 and STM32F10xxB,
 
  *                  STM32F101xC/D/E and STM32F103xC/D/E,
 
  *                  STM32F101xF/G and STM32F103xF/G
 
  *                  STM32F10xx4 and STM32F10xx6
 
  *       Debug registers DBGMCU_IDCODE and DBGMCU_CR are accessible only in 
 
  *       debug mode (not accessible by the user software in normal mode).
 
  *       Refer to errata sheet of these devices for more details.
 
  * @retval None
 
  */
 
void HAL_DBGMCU_DisableDBGStopMode(void)
 
{
 
  CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
 
}
 

	
 
/**
 
  * @brief  Enable the Debug Module during STANDBY mode
 
  * Note: On devices STM32F10xx8 and STM32F10xxB,
 
  *                  STM32F101xC/D/E and STM32F103xC/D/E,
 
  *                  STM32F101xF/G and STM32F103xF/G
 
  *                  STM32F10xx4 and STM32F10xx6
 
  *       Debug registers DBGMCU_IDCODE and DBGMCU_CR are accessible only in 
 
  *       debug mode (not accessible by the user software in normal mode).
 
  *       Refer to errata sheet of these devices for more details.
 
  * @retval None
 
  */
 
void HAL_DBGMCU_EnableDBGStandbyMode(void)
 
{
 
  SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
 
}
 

	
 
/**
 
  * @brief  Disable the Debug Module during STANDBY mode
 
  * Note: On devices STM32F10xx8 and STM32F10xxB,
 
  *                  STM32F101xC/D/E and STM32F103xC/D/E,
 
  *                  STM32F101xF/G and STM32F103xF/G
 
  *                  STM32F10xx4 and STM32F10xx6
 
  *       Debug registers DBGMCU_IDCODE and DBGMCU_CR are accessible only in 
 
  *       debug mode (not accessible by the user software in normal mode).
 
  *       Refer to errata sheet of these devices for more details.
 
  * @retval None
 
  */
 
void HAL_DBGMCU_DisableDBGStandbyMode(void)
 
{
 
  CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
 
}
 

	
 
/**
 
  * @brief Return the unique device identifier (UID based on 96 bits)
 
  * @param UID: pointer to 3 words array.
 
  * @retval Device identifier
 
  */
 
void HAL_GetUID(uint32_t *UID)
 
{
 
  UID[0] = (uint32_t)(READ_REG(*((uint32_t *)UID_BASE)));
 
  UID[1] = (uint32_t)(READ_REG(*((uint32_t *)(UID_BASE + 4U))));
 
  UID[2] = (uint32_t)(READ_REG(*((uint32_t *)(UID_BASE + 8U))));
 
}
 

	
 
/**
 
  * @}
 
  */
 

	
 
/**
 
  * @}
 
  */
 

	
 
#endif /* HAL_MODULE_ENABLED */
 
/**
 
  * @}
 
  */
 

	
 
/**
 
  * @}
 
  */
 

	
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Software/hoverboard-firmware-hack_modified20190825/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c
Show inline comments
 
new file 100644
 
/**
 
  ******************************************************************************
 
  * @file    stm32f1xx_hal_adc.c
 
  * @author  MCD Application Team
 
  * @version V1.1.1
 
  * @date    12-May-2017
 
  * @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)
 

	
 
    [..]
 
  
 
    @endverbatim
 
  ******************************************************************************
 
  * @attention
 
  *
 
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
 
  *
 
  * Redistribution and use in source and binary forms, with or without modification,
 
  * are permitted provided that the following conditions are met:
 
  *   1. Redistributions of source code must retain the above copyright notice,
 
  *      this list of conditions and the following disclaimer.
 
  *   2. Redistributions in binary form must reproduce the above copyright notice,
 
  *      this list of conditions and the following disclaimer in the documentation
 
  *      and/or other materials provided with the distribution.
 
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
 
  *      may be used to endorse or promote products derived from this software
 
  *      without specific prior written permission.
 
  *
 
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  *
 
  ******************************************************************************  
 
  */
 

	
 
/* Includes ------------------------------------------------------------------*/
 
#include "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;
 
    
 
    /* Init the low level hardware */
 
    HAL_ADC_MspInit(hadc);
 
  }
 
  
 
  /* 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(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()                                        */
 
    
 
    /* DeInit the low level hardware */
 
    HAL_ADC_MspDeInit(hadc);
 
    
 
    /* 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.
 
   */ 
 
}
 

	
 
/**
 
  * @}
 
  */
 

	
 
/** @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))
 
        {
 
          /* 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))
 
        {
 
          /* 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))
 
      {
 
        /* 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)                                              */
 
    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 */
 
      HAL_ADC_ConvCpltCallback(hadc);
 
      
 
      /* 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 */ 
 
      HAL_ADCEx_InjectedConvCpltCallback(hadc);
 
      
 
      /* 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 */ 
 
      HAL_ADC_LevelOutOfWindowCallback(hadc);
 
      
 
      /* 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)
 
      {
 
        /* 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)
 
      {
 
        /* 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 */
 
    HAL_ADC_ConvCpltCallback(hadc); 
 
  }
 
  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 */
 
  HAL_ADC_ConvHalfCpltCallback(hadc); 
 
}
 

	
 
/**
 
  * @brief  DMA error callback 
 
  * @param  hdma: pointer to DMA handle.
 
  * @retval None
 
  */
 
void ADC_DMAError(DMA_HandleTypeDef *hdma)   
 
{
 
  /* Retrieve ADC handle corresponding to current DMA handle */
 
  ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
 
  
 
  /* 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 */
 
  HAL_ADC_ErrorCallback(hadc); 
 
}
 

	
 
/**
 
  * @}
 
  */
 

	
 
#endif /* HAL_ADC_MODULE_ENABLED */
 
/**
 
  * @}
 
  */
 

	
 
/**
 
  * @}
 
  */
 

	
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Software/hoverboard-firmware-hack_modified20190825/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c
Show inline comments
 
new file 100644
 
/**
 
  ******************************************************************************
 
  * @file    stm32f1xx_hal_adc_ex.c
 
  * @author  MCD Application Team
 
  * @version V1.1.1
 
  * @date    12-May-2017
 
  * @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
 
  *
 
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
 
  *
 
  * Redistribution and use in source and binary forms, with or without modification,
 
  * are permitted provided that the following conditions are met:
 
  *   1. Redistributions of source code must retain the above copyright notice,
 
  *      this list of conditions and the following disclaimer.
 
  *   2. Redistributions in binary form must reproduce the above copyright notice,
 
  *      this list of conditions and the following disclaimer in the documentation
 
  *      and/or other materials provided with the distribution.
 
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
 
  *      may be used to endorse or promote products derived from this software
 
  *      without specific prior written permission.
 
  *
 
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  *
 
  ******************************************************************************  
 
  */
 

	
 
/* Includes ------------------------------------------------------------------*/
 
#include "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)
 
      {
 
        /* 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)
 
      {
 
        /* 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))
 
        {
 
          /* 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))
 
        {
 
          /* 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;
 

	
 
  /* 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;
 
  
 
  /* 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;
 
  
 
  /* 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****/
Software/hoverboard-firmware-hack_modified20190825/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_can.c
Show inline comments
 
new file 100644
 
/**
 
  ******************************************************************************
 
  * @file    stm32f1xx_hal_can.c
 
  * @author  MCD Application Team
 
  * @version V1.1.1
 
  * @date    12-May-2017
 
  * @brief   CAN HAL module driver.
 
  *          This file provides firmware functions to manage the following 
 
  *          functionalities of the Controller Area Network (CAN) peripheral:           
 
  *           + Initialization and de-initialization functions 
 
  *           + IO operation functions
 
  *           + Peripheral Control functions
 
  *           + Peripheral State and Error functions
 
  *
 
  @verbatim
 
  ==============================================================================
 
                        ##### How to use this driver #####
 
  ==============================================================================
 
    [..]            
 
      (#) Enable the CAN controller interface clock using 
 
          __HAL_RCC_CAN1_CLK_ENABLE() for CAN1 and __HAL_RCC_CAN2_CLK_ENABLE() for CAN2
 
      -@- In case you are using CAN2 only, you have to enable the CAN1 clock.
 
       
 
      (#) CAN pins configuration
 
        (++) Enable the clock for the CAN GPIOs using the following function:
 
             __HAL_RCC_GPIOx_CLK_ENABLE();   
 
        (++) Connect and configure the involved CAN pins using the 
 
              following function HAL_GPIO_Init(); 
 
              
 
      (#) Initialize and configure the CAN using HAL_CAN_Init() function.   
 
                 
 
      (#) Transmit the desired CAN frame using HAL_CAN_Transmit() function.
 

	
 
      (#) Or transmit the desired CAN frame using HAL_CAN_Transmit_IT() function.
 
           
 
      (#) Receive a CAN frame using HAL_CAN_Receive() function.
 

	
 
      (#) Or receive a CAN frame using HAL_CAN_Receive_IT() function.
 

	
 
     *** Polling mode IO operation ***
 
     =================================
 
     [..]    
 
       (+) Start the CAN peripheral transmission and wait the end of this operation 
 
           using HAL_CAN_Transmit(), at this stage user can specify the value of timeout
 
           according to his end application
 
       (+) Start the CAN peripheral reception and wait the end of this operation 
 
           using HAL_CAN_Receive(), at this stage user can specify the value of timeout
 
           according to his end application 
 
       
 
     *** Interrupt mode IO operation ***    
 
     ===================================
 
     [..]    
 
       (+) Start the CAN peripheral transmission using HAL_CAN_Transmit_IT()
 
       (+) Start the CAN peripheral reception using HAL_CAN_Receive_IT()         
 
       (+) Use HAL_CAN_IRQHandler() called under the used CAN Interrupt subroutine
 
       (+) At CAN end of transmission HAL_CAN_TxCpltCallback() function is executed and user can 
 
            add his own code by customization of function pointer HAL_CAN_TxCpltCallback 
 
       (+) In case of CAN Error, HAL_CAN_ErrorCallback() function is executed and user can 
 
            add his own code by customization of function pointer HAL_CAN_ErrorCallback
 
 
 
     *** CAN HAL driver macros list ***
 
     ============================================= 
 
     [..]
 
       Below the list of most used macros in CAN HAL driver.
 
       
 
      (+) __HAL_CAN_ENABLE_IT: Enable the specified CAN interrupts
 
      (+) __HAL_CAN_DISABLE_IT: Disable the specified CAN interrupts
 
      (+) __HAL_CAN_GET_IT_SOURCE: Check if the specified CAN interrupt source is enabled or disabled
 
      (+) __HAL_CAN_CLEAR_FLAG: Clear the CAN's pending flags
 
      (+) __HAL_CAN_GET_FLAG: Get the selected CAN's flag status
 
      
 
     [..] 
 
      (@) You can refer to the CAN HAL driver header file for more useful macros 
 
                
 
  @endverbatim
 
           
 
  ******************************************************************************
 
  * @attention
 
  *
 
  * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
 
  *
 
  * Redistribution and use in source and binary forms, with or without modification,
 
  * are permitted provided that the following conditions are met:
 
  *   1. Redistributions of source code must retain the above copyright notice,
 
  *      this list of conditions and the following disclaimer.
 
  *   2. Redistributions in binary form must reproduce the above copyright notice,
 
  *      this list of conditions and the following disclaimer in the documentation
 
  *      and/or other materials provided with the distribution.
 
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
 
  *      may be used to endorse or promote products derived from this software
 
  *      without specific prior written permission.
 
  *
 
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  *
 
  ******************************************************************************
 
  */
 

	
 
/* Includes ------------------------------------------------------------------*/
 
#include "stm32f1xx_hal.h"
 

	
 
/** @addtogroup STM32F1xx_HAL_Driver
 
  * @{
 
  */
 

	
 
/** @defgroup CAN CAN
 
  * @brief CAN driver modules
 
  * @{
 
  */
 

	
 
#ifdef HAL_CAN_MODULE_ENABLED  
 
  
 
#if defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || \
 
    defined(STM32F103xG) || defined(STM32F105xC) || defined(STM32F107xC)
 
  
 

	
 
/* Private typedef -----------------------------------------------------------*/
 
/* Private define ------------------------------------------------------------*/
 
/** @defgroup CAN_Private_Constants CAN Private Constants
 
  * @{
 
  */
 
#define CAN_TIMEOUT_VALUE  10U
 
/**
 
  * @}
 
  */
 
/* Private macro -------------------------------------------------------------*/
 
/* Private variables ---------------------------------------------------------*/
 
/* Private function prototypes -----------------------------------------------*/
 
/** @defgroup CAN_Private_Functions CAN Private Functions
 
  * @{
 
  */
 
static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber);
 
static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan);
 
/**
 
  * @}
 
  */
 

	
 
/* Exported functions --------------------------------------------------------*/
 
/** @defgroup CAN_Exported_Functions CAN Exported Functions
 
  * @{
 
  */
 

	
 
/** @defgroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions 
 
 *  @brief    Initialization and Configuration functions 
 
 *
 
@verbatim    
 
  ==============================================================================
 
              ##### Initialization and de-initialization functions #####
 
  ==============================================================================
 
    [..]  This section provides functions allowing to:
 
      (+) Initialize and configure the CAN. 
 
      (+) De-initialize the CAN. 
 
         
 
@endverbatim
 
  * @{
 
  */
 
  
 
/**
 
  * @brief  Initializes the CAN peripheral according to the specified
 
  *         parameters in the CAN_InitStruct.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan)
 
{
 
  uint32_t status = CAN_INITSTATUS_FAILED;  /* Default init status */
 
  uint32_t tickstart = 0U;
 
  uint32_t tmp_mcr = 0U;
 
  
 
  /* Check CAN handle */
 
  if(hcan == NULL)
 
  {
 
     return HAL_ERROR;
 
  }
 

	
 
  /* Check the parameters */
 
  assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance));
 
  assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TTCM));
 
  assert_param(IS_FUNCTIONAL_STATE(hcan->Init.ABOM));
 
  assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AWUM));
 
  assert_param(IS_FUNCTIONAL_STATE(hcan->Init.NART));
 
  assert_param(IS_FUNCTIONAL_STATE(hcan->Init.RFLM));
 
  assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TXFP));
 
  assert_param(IS_CAN_MODE(hcan->Init.Mode));
 
  assert_param(IS_CAN_SJW(hcan->Init.SJW));
 
  assert_param(IS_CAN_BS1(hcan->Init.BS1));
 
  assert_param(IS_CAN_BS2(hcan->Init.BS2));
 
  assert_param(IS_CAN_PRESCALER(hcan->Init.Prescaler));
 
  
 
  if(hcan->State == HAL_CAN_STATE_RESET)
 
  {
 
    /* Allocate lock resource and initialize it */
 
    hcan->Lock = HAL_UNLOCKED;
 
    /* Init the low level hardware */
 
    HAL_CAN_MspInit(hcan);
 
  }
 
  
 
  /* Initialize the CAN state*/
 
  hcan->State = HAL_CAN_STATE_BUSY;
 
  
 
  /* Exit from sleep mode */
 
  CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);
 

	
 
  /* Request initialisation */
 
  SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ);
 

	
 
  /* Get timeout */
 
  tickstart = HAL_GetTick();   
 
  
 
  /* Wait the acknowledge */
 
  while(HAL_IS_BIT_CLR(hcan->Instance->MSR, CAN_MSR_INAK))
 
  {
 
    if((HAL_GetTick()-tickstart) > CAN_TIMEOUT_VALUE)
 
    {
 
      hcan->State= HAL_CAN_STATE_TIMEOUT;
 
      /* Process unlocked */
 
      __HAL_UNLOCK(hcan);
 
      return HAL_TIMEOUT;
 
    }
 
  }
 

	
 
  /* Check acknowledge */
 
  if ((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
 
  {
 
    /* Set the time triggered communication mode */
 
    if (hcan->Init.TTCM == ENABLE)
 
    {
 
      SET_BIT(tmp_mcr, CAN_MCR_TTCM);
 
    }
 
    else
 
    {
 
      CLEAR_BIT(tmp_mcr, CAN_MCR_TTCM);
 
    }
 

	
 
    /* Set the automatic bus-off management */
 
    if (hcan->Init.ABOM == ENABLE)
 
    {
 
      SET_BIT(tmp_mcr, CAN_MCR_ABOM);
 
    }
 
    else
 
    {
 
      CLEAR_BIT(tmp_mcr, CAN_MCR_ABOM);
 
    }
 

	
 
    /* Set the automatic wake-up mode */
 
    if (hcan->Init.AWUM == ENABLE)
 
    {
 
      SET_BIT(tmp_mcr, CAN_MCR_AWUM);
 
    }
 
    else
 
    {
 
      CLEAR_BIT(tmp_mcr, CAN_MCR_AWUM);
 
    }
 
    /* Set the no automatic retransmission */
 
    if (hcan->Init.NART == ENABLE)
 
    {
 
      SET_BIT(tmp_mcr, CAN_MCR_NART);
 
    }
 
    else
 
    {
 
      CLEAR_BIT(tmp_mcr, CAN_MCR_NART);
 
    }
 

	
 
    /* Set the receive FIFO locked mode */
 
    if (hcan->Init.RFLM == ENABLE)
 
    {
 
      SET_BIT(tmp_mcr, CAN_MCR_RFLM);
 
    }
 
    else
 
    {
 
      CLEAR_BIT(tmp_mcr, CAN_MCR_RFLM);
 
    }
 
    /* Set the transmit FIFO priority */
 
    if (hcan->Init.TXFP == ENABLE)
 
    {
 
      SET_BIT(tmp_mcr, CAN_MCR_TXFP);
 
    }
 
    else
 
    {
 
      CLEAR_BIT(tmp_mcr, CAN_MCR_TXFP);
 
    }
 
    
 
    /* Update register MCR */
 
    MODIFY_REG(hcan->Instance->MCR,
 
               CAN_MCR_TTCM |
 
               CAN_MCR_ABOM |
 
               CAN_MCR_AWUM |
 
               CAN_MCR_NART |
 
               CAN_MCR_RFLM |
 
               CAN_MCR_TXFP,
 
               tmp_mcr);
 
    
 
    /* Set the bit timing register */
 
    WRITE_REG(hcan->Instance->BTR, (uint32_t)(hcan->Init.Mode           |
 
                                              hcan->Init.SJW            |
 
                                              hcan->Init.BS1            |
 
                                              hcan->Init.BS2            |
 
                                              (hcan->Init.Prescaler - 1U)));
 

	
 
    /* Request leave initialisation */
 
    CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_INRQ);
 

	
 
    /* Get timeout */
 
    tickstart = HAL_GetTick();   
 
   
 
    /* Wait the acknowledge */
 
    while(HAL_IS_BIT_SET(hcan->Instance->MSR, CAN_MSR_INAK))
 
    {
 
      if((HAL_GetTick()-tickstart) > CAN_TIMEOUT_VALUE)
 
      {
 
        hcan->State= HAL_CAN_STATE_TIMEOUT;
 

	
 
        /* Process unlocked */
 
        __HAL_UNLOCK(hcan);
 

	
 
        return HAL_TIMEOUT;
 
      }
 
    }
 

	
 
    /* Check acknowledged */
 
    if(HAL_IS_BIT_CLR(hcan->Instance->MSR, CAN_MSR_INAK))
 
    {
 
      status = CAN_INITSTATUS_SUCCESS;
 
    }
 
  }
 
 
 
  if(status == CAN_INITSTATUS_SUCCESS)
 
  {
 
    /* Set CAN error code to none */
 
    hcan->ErrorCode = HAL_CAN_ERROR_NONE;
 
    
 
    /* Initialize the CAN state */
 
    hcan->State = HAL_CAN_STATE_READY;
 
  
 
    /* Return function status */
 
    return HAL_OK;
 
  }
 
  else
 
  {
 
    /* Initialize the CAN state */
 
    hcan->State = HAL_CAN_STATE_ERROR;
 

	
 
    /* Return function status */
 
    return HAL_ERROR;
 
  }
 
}
 

	
 
/**
 
  * @brief  Configures the CAN reception filter according to the specified
 
  *         parameters in the CAN_FilterInitStruct.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.
 
  * @param  sFilterConfig: pointer to a CAN_FilterConfTypeDef structure that
 
  *         contains the filter configuration information.
 
  * @retval None
 
  */
 
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig)
 
{
 
  uint32_t filternbrbitpos = 0U;
 
  
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcan);
 

	
 
  /* Check the parameters */
 
  assert_param(IS_CAN_FILTER_NUMBER(sFilterConfig->FilterNumber));
 
  assert_param(IS_CAN_FILTER_MODE(sFilterConfig->FilterMode));
 
  assert_param(IS_CAN_FILTER_SCALE(sFilterConfig->FilterScale));
 
  assert_param(IS_CAN_FILTER_FIFO(sFilterConfig->FilterFIFOAssignment));
 
  assert_param(IS_FUNCTIONAL_STATE(sFilterConfig->FilterActivation));
 
  assert_param(IS_CAN_BANKNUMBER(sFilterConfig->BankNumber));
 
  
 
  filternbrbitpos = (1U) << sFilterConfig->FilterNumber;
 

	
 
  /* Initialisation mode for the filter */
 
  /* Select the start slave bank */
 
  MODIFY_REG(hcan->Instance->FMR                         ,
 
             CAN_FMR_CAN2SB                              ,
 
             CAN_FMR_FINIT                              |
 
             (uint32_t)(sFilterConfig->BankNumber << 8U)   );
 

	
 
  /* Filter Deactivation */
 
  CLEAR_BIT(hcan->Instance->FA1R, filternbrbitpos);
 

	
 
  /* Filter Scale */
 
  if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT)
 
  {
 
    /* 16-bit scale for the filter */
 
    CLEAR_BIT(hcan->Instance->FS1R, filternbrbitpos);
 

	
 
    /* First 16-bit identifier and First 16-bit mask */
 
    /* Or First 16-bit identifier and Second 16-bit identifier */
 
    hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR1 = 
 
       ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16U) |
 
        (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow);
 

	
 
    /* Second 16-bit identifier and Second 16-bit mask */
 
    /* Or Third 16-bit identifier and Fourth 16-bit identifier */
 
    hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR2 = 
 
       ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |
 
        (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh);
 
  }
 

	
 
  if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)
 
  {
 
    /* 32-bit scale for the filter */
 
    SET_BIT(hcan->Instance->FS1R, filternbrbitpos);
 
    /* 32-bit identifier or First 32-bit identifier */
 
    hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR1 = 
 
       ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh) << 16U) |
 
        (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow);
 
    /* 32-bit mask or Second 32-bit identifier */
 
    hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR2 = 
 
       ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |
 
        (0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow);
 
  }
 

	
 
  /* Filter Mode */
 
  if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK)
 
  {
 
    /*Id/Mask mode for the filter*/
 
    CLEAR_BIT(hcan->Instance->FM1R, filternbrbitpos);
 
  }
 
  else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
 
  {
 
    /*Identifier list mode for the filter*/
 
    SET_BIT(hcan->Instance->FM1R, filternbrbitpos);
 
  }
 

	
 
  /* Filter FIFO assignment */
 
  if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0)
 
  {
 
    /* FIFO 0 assignation for the filter */
 
    CLEAR_BIT(hcan->Instance->FFA1R, filternbrbitpos);
 
  }
 
  else
 
  {
 
    /* FIFO 1 assignation for the filter */
 
    SET_BIT(hcan->Instance->FFA1R, filternbrbitpos);
 
  }
 
  
 
  /* Filter activation */
 
  if (sFilterConfig->FilterActivation == ENABLE)
 
  {
 
    SET_BIT(hcan->Instance->FA1R, filternbrbitpos);
 
  }
 

	
 
  /* Leave the initialisation mode for the filter */
 
  CLEAR_BIT(hcan->Instance->FMR, ((uint32_t)CAN_FMR_FINIT));
 
  
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief  Deinitializes the CANx peripheral registers to their default reset values. 
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef* hcan)
 
{
 
  /* Check CAN handle */
 
  if(hcan == NULL)
 
  {
 
     return HAL_ERROR;
 
  }
 
  
 
  /* Check the parameters */
 
  assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance));
 
  
 
  /* Change CAN state */
 
  hcan->State = HAL_CAN_STATE_BUSY;
 
  
 
  /* DeInit the low level hardware */
 
  HAL_CAN_MspDeInit(hcan);
 
  
 
  /* Change CAN state */
 
  hcan->State = HAL_CAN_STATE_RESET;
 

	
 
  /* Release Lock */
 
  __HAL_UNLOCK(hcan);
 

	
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief  Initializes the CAN MSP.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @retval None
 
  */
 
__weak void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcan);
 
  /* NOTE : This function Should not be modified, when the callback is needed,
 
            the HAL_CAN_MspInit can be implemented in the user file
 
   */ 
 
}
 

	
 
/**
 
  * @brief  DeInitializes the CAN MSP.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @retval None
 
  */
 
__weak void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcan);
 
  /* NOTE : This function Should not be modified, when the callback is needed,
 
            the HAL_CAN_MspDeInit can be implemented in the user file
 
   */ 
 
}
 

	
 
/**
 
  * @}
 
  */
 

	
 
/** @defgroup CAN_Exported_Functions_Group2 Input and Output operation functions
 
  *  @brief    I/O operation functions 
 
  *
 
@verbatim   
 
  ==============================================================================
 
                      ##### IO operation functions #####
 
  ==============================================================================
 
    [..]  This section provides functions allowing to:
 
      (+) Transmit a CAN frame message.
 
      (+) Receive a CAN frame message.
 
      (+) Enter CAN peripheral in sleep mode. 
 
      (+) Wake up the CAN peripheral from sleep mode.
 
               
 
@endverbatim
 
  * @{
 
  */
 

	
 
/**
 
  * @brief  Initiates and transmits a CAN frame message.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @param  Timeout: Specify Timeout value   
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout)
 
{
 
  uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
 
  uint32_t tickstart = 0U;
 

	
 
  /* Check the parameters */
 
  assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));
 
  assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));
 
  assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));
 

	
 
  if(((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) || \
 
     ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) || \
 
     ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2))
 
  {
 
    /* Process locked */
 
    __HAL_LOCK(hcan);
 

	
 
    /* Change CAN state */
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_RX0):
 
          hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
 
          break;
 
      case(HAL_CAN_STATE_BUSY_RX1):
 
          hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
 
          break;
 
      case(HAL_CAN_STATE_BUSY_RX0_RX1):
 
          hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
 
          break;
 
      default: /* HAL_CAN_STATE_READY */
 
          hcan->State = HAL_CAN_STATE_BUSY_TX;
 
          break;
 
    }
 

	
 
    /* Select one empty transmit mailbox */
 
    if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME0))
 
    {
 
      transmitmailbox = CAN_TXMAILBOX_0;
 
    }
 
    else if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME1))
 
    {
 
      transmitmailbox = CAN_TXMAILBOX_1;
 
    }
 
    else
 
    {
 
      transmitmailbox = CAN_TXMAILBOX_2;
 
    }
 

	
 
    /* Set up the Id */
 
    hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
 
    if (hcan->pTxMsg->IDE == CAN_ID_STD)
 
    {
 
      assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));  
 
      hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << CAN_TI0R_STID_Pos) |
 
                                                           hcan->pTxMsg->RTR);
 
    }
 
    else
 
    {
 
      assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));
 
      hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << CAN_TI0R_EXID_Pos) |
 
                                                           hcan->pTxMsg->IDE |
 
                                                           hcan->pTxMsg->RTR);
 
    }
 

	
 
    /* Set up the DLC */
 
    hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;
 
    hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= 0xFFFFFFF0U;
 
    hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;
 

	
 
    /* Set up the data field */
 
    WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDLR, ((uint32_t)hcan->pTxMsg->Data[3] << CAN_TDL0R_DATA3_Pos) | 
 
                                                                ((uint32_t)hcan->pTxMsg->Data[2] << CAN_TDL0R_DATA2_Pos) |
 
                                                                ((uint32_t)hcan->pTxMsg->Data[1] << CAN_TDL0R_DATA1_Pos) | 
 
                                                                ((uint32_t)hcan->pTxMsg->Data[0] << CAN_TDL0R_DATA0_Pos));
 
    WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDHR, ((uint32_t)hcan->pTxMsg->Data[7] << CAN_TDL0R_DATA3_Pos) | 
 
                                                                ((uint32_t)hcan->pTxMsg->Data[6] << CAN_TDL0R_DATA2_Pos) |
 
                                                                ((uint32_t)hcan->pTxMsg->Data[5] << CAN_TDL0R_DATA1_Pos) |
 
                                                                ((uint32_t)hcan->pTxMsg->Data[4] << CAN_TDL0R_DATA0_Pos));
 
    /* Request transmission */
 
    SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TIR, CAN_TI0R_TXRQ);
 

	
 
    /* Get tick */
 
    tickstart = HAL_GetTick();
 

	
 
    /* Check End of transmission flag */
 
    while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))
 
    {
 
      /* Check for the Timeout */
 
      if(Timeout != HAL_MAX_DELAY)
 
      {
 
        if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
 
        {
 
          hcan->State = HAL_CAN_STATE_TIMEOUT;
 

	
 
          /* Cancel transmission */
 
          __HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox);
 

	
 
          /* Process unlocked */
 
          __HAL_UNLOCK(hcan);
 
          return HAL_TIMEOUT;
 
        }
 
      }
 
    }
 
    /* Change CAN state */
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_TX_RX0):
 
          hcan->State = HAL_CAN_STATE_BUSY_RX0;
 
          break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX1):
 
          hcan->State = HAL_CAN_STATE_BUSY_RX1;
 
          break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
 
          hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
 
          break;
 
      default: /* HAL_CAN_STATE_BUSY_TX */
 
          hcan->State = HAL_CAN_STATE_READY;
 
          break;
 
    }
 

	
 
    /* Process unlocked */
 
    __HAL_UNLOCK(hcan);
 

	
 
    /* Return function status */
 
    return HAL_OK;
 
  }
 
  else
 
  {
 
    /* Change CAN state */
 
    hcan->State = HAL_CAN_STATE_ERROR;
 

	
 
    /* Return function status */
 
    return HAL_ERROR;
 
  }
 
}
 

	
 
/**
 
  * @brief  Initiates and transmits a CAN frame message.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CAN_Transmit_IT(CAN_HandleTypeDef* hcan)
 
{
 
  uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
 

	
 
  /* Check the parameters */
 
  assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));
 
  assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));
 
  assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));
 
  
 
  if(((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) || \
 
     ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) || \
 
     ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2))
 
  {
 
    /* Process Locked */
 
    __HAL_LOCK(hcan);
 
    
 
    /* Select one empty transmit mailbox */
 
    if(HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME0))
 
    {
 
      transmitmailbox = CAN_TXMAILBOX_0;
 
    }
 
    else if(HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME1))
 
    {
 
      transmitmailbox = CAN_TXMAILBOX_1;
 
    }
 
    else
 
    {
 
      transmitmailbox = CAN_TXMAILBOX_2;
 
    }
 

	
 
    /* Set up the Id */
 
    hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
 
    if(hcan->pTxMsg->IDE == CAN_ID_STD)
 
    {
 
      assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));
 
      hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << CAN_TI0R_STID_Pos) | \
 
                                                           hcan->pTxMsg->RTR);
 
    }
 
    else
 
    {
 
      assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));
 
      hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << CAN_TI0R_EXID_Pos) | \
 
                                                           hcan->pTxMsg->IDE |
 
                                                           hcan->pTxMsg->RTR);
 
    }
 

	
 
    /* Set up the DLC */
 
    hcan->pTxMsg->DLC &= (uint8_t)0x0000000FU;
 
    hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= 0xFFFFFFF0U;
 
    hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;
 

	
 
    /* Set up the data field */
 
    WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDLR, ((uint32_t)hcan->pTxMsg->Data[3U] << CAN_TDL0R_DATA3_Pos) |
 
                                                                ((uint32_t)hcan->pTxMsg->Data[2U] << CAN_TDL0R_DATA2_Pos) |
 
                                                                ((uint32_t)hcan->pTxMsg->Data[1U] << CAN_TDL0R_DATA1_Pos) |
 
                                                                ((uint32_t)hcan->pTxMsg->Data[0U] << CAN_TDL0R_DATA0_Pos));
 
    WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDHR, ((uint32_t)hcan->pTxMsg->Data[7U] << CAN_TDL0R_DATA3_Pos) |
 
                                                                ((uint32_t)hcan->pTxMsg->Data[6U] << CAN_TDL0R_DATA2_Pos) |
 
                                                                ((uint32_t)hcan->pTxMsg->Data[5U] << CAN_TDL0R_DATA1_Pos) |
 
                                                                ((uint32_t)hcan->pTxMsg->Data[4U] << CAN_TDL0R_DATA0_Pos));
 

	
 
    /* Change CAN state */
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_RX0):
 
          hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
 
          break;
 
      case(HAL_CAN_STATE_BUSY_RX1):
 
          hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
 
          break;
 
      case(HAL_CAN_STATE_BUSY_RX0_RX1):
 
          hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
 
          break;
 
      default: /* HAL_CAN_STATE_READY */
 
          hcan->State = HAL_CAN_STATE_BUSY_TX;
 
          break;
 
    }
 

	
 
    /* Set CAN error code to none */
 
    hcan->ErrorCode = HAL_CAN_ERROR_NONE;
 

	
 
    /* Process Unlocked */
 
    __HAL_UNLOCK(hcan);
 

	
 
    /* Request transmission */
 
    hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
 

	
 
    /* Enable interrupts: */
 
    /*  - Enable Error warning Interrupt */
 
    /*  - Enable Error passive Interrupt */
 
    /*  - Enable Bus-off Interrupt */
 
    /*  - Enable Last error code Interrupt */
 
    /*  - Enable Error Interrupt */
 
    /*  - Enable Transmit mailbox empty Interrupt */
 
    __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |
 
                              CAN_IT_EPV |
 
                              CAN_IT_BOF |
 
                              CAN_IT_LEC |
 
                              CAN_IT_ERR |
 
                              CAN_IT_TME  );
 
  }
 
  else
 
  {
 
    /* Change CAN state */
 
    hcan->State = HAL_CAN_STATE_ERROR;
 

	
 
    /* Return function status */
 
    return HAL_ERROR;
 
  }
 

	
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief  Receives a correct CAN frame.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @param  FIFONumber: FIFO Number value
 
  * @param  Timeout: Specify Timeout value 
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef* hcan, uint8_t FIFONumber, uint32_t Timeout)
 
{
 
  uint32_t tickstart = 0U;
 
  CanRxMsgTypeDef* pRxMsg = NULL;
 

	
 
  /* Check the parameters */
 
  assert_param(IS_CAN_FIFO(FIFONumber));
 

	
 
  /* Check if CAN state is not busy for RX FIFO0 */
 
  if ((FIFONumber == CAN_FIFO0) && ((hcan->State == HAL_CAN_STATE_BUSY_RX0) ||         \
 
                                    (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0) ||      \
 
                                    (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) ||     \
 
                                    (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1)))
 
  {
 
    return HAL_BUSY;
 
  }
 

	
 
  /* Check if CAN state is not busy for RX FIFO1 */
 
  if ((FIFONumber == CAN_FIFO1) && ((hcan->State == HAL_CAN_STATE_BUSY_RX1) ||         \
 
                                    (hcan->State == HAL_CAN_STATE_BUSY_TX_RX1) ||      \
 
                                    (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) ||     \
 
                                    (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1)))
 
  {
 
    return HAL_BUSY;
 
  }
 

	
 
  /* Process locked */
 
  __HAL_LOCK(hcan);
 

	
 
  /* Change CAN state */
 
  if (FIFONumber == CAN_FIFO0)
 
  {
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_TX):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
 
        break;
 
      default: /* HAL_CAN_STATE_READY */
 
        hcan->State = HAL_CAN_STATE_BUSY_RX0;
 
        break;
 
    }
 
  }
 
  else /* FIFONumber == CAN_FIFO1 */
 
  {
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_TX):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_RX0):
 
        hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX0):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
 
        break;
 
      default: /* HAL_CAN_STATE_READY */
 
        hcan->State = HAL_CAN_STATE_BUSY_RX1;
 
        break;
 
    }
 
  }
 
  /* Get tick */ 
 
  tickstart = HAL_GetTick();
 
  
 
  /* Check pending message */
 
  while(__HAL_CAN_MSG_PENDING(hcan, FIFONumber) == 0U)
 
  {
 
    /* Check for the Timeout */
 
    if(Timeout != HAL_MAX_DELAY)
 
    {
 
      if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
 
      {
 
        hcan->State = HAL_CAN_STATE_TIMEOUT;
 
        /* Process unlocked */
 
        __HAL_UNLOCK(hcan);
 
        return HAL_TIMEOUT;
 
      }
 
    }
 
  }
 

	
 
  /* Set RxMsg pointer */
 
  if(FIFONumber == CAN_FIFO0)
 
  {
 
    pRxMsg = hcan->pRxMsg;
 
  }
 
  else /* FIFONumber == CAN_FIFO1 */
 
  {
 
    pRxMsg = hcan->pRx1Msg;
 
  }
 

	
 
  /* Get the Id */
 
  pRxMsg->IDE = (uint8_t)CAN_ID_EXT & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
 
  if (pRxMsg->IDE == CAN_ID_STD)
 
  {
 
    pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21U);
 
  }
 
  else
 
  {
 
    pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3U);
 
  }
 
  
 
  pRxMsg->RTR = (uint8_t)CAN_RTR_REMOTE & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
 
  /* Get the DLC */
 
  pRxMsg->DLC = (uint8_t)0x0FU & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
 
  /* Get the FMI */
 
  pRxMsg->FMI = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8U);
 
  /* Get the FIFONumber */
 
  pRxMsg->FIFONumber = FIFONumber;
 
  /* Get the data field */
 
  pRxMsg->Data[0] = (uint8_t)0xFFU & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
 
  pRxMsg->Data[1] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8U);
 
  pRxMsg->Data[2] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16U);
 
  pRxMsg->Data[3] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24U);
 
  pRxMsg->Data[4] = (uint8_t)0xFFU & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
 
  pRxMsg->Data[5] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8U);
 
  pRxMsg->Data[6] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16U);
 
  pRxMsg->Data[7] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24U);
 
  
 
  /* Release the FIFO */
 
  if(FIFONumber == CAN_FIFO0)
 
  {
 
    /* Release FIFO0 */
 
    __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
 
  }
 
  else /* FIFONumber == CAN_FIFO1 */
 
  {
 
    /* Release FIFO1 */
 
    __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
 
  }
 
  
 
  /* Change CAN state */
 
  if (FIFONumber == CAN_FIFO0)
 
  {
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_TX_RX0):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_RX0_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_RX1;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
 
        break;
 
      default: /* HAL_CAN_STATE_BUSY_RX0 */
 
        hcan->State = HAL_CAN_STATE_READY;
 
        break;
 
    }
 
  }
 
  else /* FIFONumber == CAN_FIFO1 */
 
  {
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_TX_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_RX0_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_RX0;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
 
        break;
 
      default: /* HAL_CAN_STATE_BUSY_RX1 */
 
        hcan->State = HAL_CAN_STATE_READY;
 
        break;
 
    }
 
  }
 

	
 
  /* Process unlocked */
 
  __HAL_UNLOCK(hcan);
 

	
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief  Receives a correct CAN frame.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @param  FIFONumber: Specify the FIFO number    
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
 
{
 
  /* Check the parameters */
 
  assert_param(IS_CAN_FIFO(FIFONumber));
 
  
 
  /* Check if CAN state is not busy for RX FIFO0 */
 
  if((FIFONumber == CAN_FIFO0) && ((hcan->State == HAL_CAN_STATE_BUSY_RX0) ||         \
 
                                   (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0) ||      \
 
                                   (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) ||     \
 
                                   (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1)))
 
  {
 
    return HAL_BUSY;
 
  }
 

	
 
  /* Check if CAN state is not busy for RX FIFO1 */
 
  if((FIFONumber == CAN_FIFO1) && ((hcan->State == HAL_CAN_STATE_BUSY_RX1) ||         \
 
                                   (hcan->State == HAL_CAN_STATE_BUSY_TX_RX1) ||      \
 
                                   (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) ||     \
 
                                   (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1)))
 
  {
 
    return HAL_BUSY;
 
  }
 

	
 
  /* Process locked */
 
  __HAL_LOCK(hcan);
 

	
 
  /* Change CAN state */
 
  if(FIFONumber == CAN_FIFO0)
 
  {
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_TX):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
 
        break;
 
      default: /* HAL_CAN_STATE_READY */
 
        hcan->State = HAL_CAN_STATE_BUSY_RX0;
 
        break;
 
    }
 
  }
 
  else /* FIFONumber == CAN_FIFO1 */
 
  {
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_TX):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_RX0):
 
        hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX0):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
 
        break;
 
      default: /* HAL_CAN_STATE_READY */
 
        hcan->State = HAL_CAN_STATE_BUSY_RX1;
 
        break;
 
    }
 
  }
 
  /* Set CAN error code to none */
 
  hcan->ErrorCode = HAL_CAN_ERROR_NONE;
 

	
 

	
 
  /* Enable interrupts: */
 
  /*  - Enable Error warning Interrupt */
 
  /*  - Enable Error passive Interrupt */
 
  /*  - Enable Bus-off Interrupt */
 
  /*  - Enable Last error code Interrupt */
 
  /*  - Enable Error Interrupt */
 
  /*  - Enable Transmit mailbox empty Interrupt */
 
  __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |
 
                            CAN_IT_EPV |
 
                            CAN_IT_BOF |
 
                            CAN_IT_LEC |
 
                            CAN_IT_ERR |
 
                            CAN_IT_TME  );
 
  
 
   /* Process unlocked */
 
   __HAL_UNLOCK(hcan);
 

	
 
  if(FIFONumber == CAN_FIFO0)
 
  {
 
    /* Enable FIFO 0 overrun and message pending Interrupt */
 
    __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FOV0 | CAN_IT_FMP0);
 
  }
 
  else
 
  {
 
    /* Enable FIFO 1 overrun and message pending Interrupt */
 
    __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FOV1 | CAN_IT_FMP1);
 
  }
 

	
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief  Enters the Sleep (low power) mode.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.
 
  * @retval HAL status.
 
  */
 
HAL_StatusTypeDef HAL_CAN_Sleep(CAN_HandleTypeDef* hcan)
 
{
 
  uint32_t tickstart = 0U;
 
   
 
  /* Process locked */
 
  __HAL_LOCK(hcan);
 
  
 
  /* Change CAN state */
 
  hcan->State = HAL_CAN_STATE_BUSY; 
 
    
 
  /* Request Sleep mode */
 
  MODIFY_REG(hcan->Instance->MCR,
 
             CAN_MCR_INRQ       ,
 
             CAN_MCR_SLEEP       );
 

	
 
  /* Sleep mode status */
 
  if (HAL_IS_BIT_CLR(hcan->Instance->MSR, CAN_MSR_SLAK) ||
 
      HAL_IS_BIT_SET(hcan->Instance->MSR, CAN_MSR_INAK)   )
 
  {
 
    /* Process unlocked */
 
    __HAL_UNLOCK(hcan);
 

	
 
    /* Return function status */
 
    return HAL_ERROR;
 
  }
 
  
 
  /* Get tick */
 
  tickstart = HAL_GetTick();
 
  
 
  /* Wait the acknowledge */
 
  while (HAL_IS_BIT_CLR(hcan->Instance->MSR, CAN_MSR_SLAK) ||
 
         HAL_IS_BIT_SET(hcan->Instance->MSR, CAN_MSR_INAK))
 
  {
 
    if((HAL_GetTick()-tickstart) > CAN_TIMEOUT_VALUE)
 
    {
 
      hcan->State = HAL_CAN_STATE_TIMEOUT;
 

	
 
      /* Process unlocked */
 
      __HAL_UNLOCK(hcan);
 

	
 
      return HAL_TIMEOUT;
 
    }
 
  }
 
  
 
  /* Change CAN state */
 
  hcan->State = HAL_CAN_STATE_READY;
 
  
 
  /* Process unlocked */
 
  __HAL_UNLOCK(hcan);
 
  
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief  Wakes up the CAN peripheral from sleep mode, after that the CAN peripheral
 
  *         is in the normal mode.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.
 
  * @retval HAL status.
 
  */
 
HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef* hcan)
 
{
 
  uint32_t tickstart = 0U;
 
    
 
  /* Process locked */
 
  __HAL_LOCK(hcan);
 
  
 
  /* Change CAN state */
 
  hcan->State = HAL_CAN_STATE_BUSY;  
 
 
 
  /* Wake up request */
 
  CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);
 
    
 
  /* Get timeout */
 
  tickstart = HAL_GetTick();   
 
  
 
  /* Sleep mode status */
 
  while((hcan->Instance->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK)
 
  {
 
    if((HAL_GetTick()-tickstart) > CAN_TIMEOUT_VALUE)
 
    {
 
      hcan->State= HAL_CAN_STATE_TIMEOUT;
 
      /* Process unlocked */
 
      __HAL_UNLOCK(hcan);
 
      return HAL_TIMEOUT;
 
    }
 
  }
 
  if(HAL_IS_BIT_SET(hcan->Instance->MSR, CAN_MSR_SLAK))
 
  {
 
    /* Process unlocked */
 
    __HAL_UNLOCK(hcan);
 

	
 
    /* Return function status */
 
    return HAL_ERROR;
 
  }
 
  
 
  /* Change CAN state */
 
  hcan->State = HAL_CAN_STATE_READY; 
 
  
 
  /* Process unlocked */
 
  __HAL_UNLOCK(hcan);
 
  
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief  Handles CAN interrupt request  
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.
 
  * @retval None
 
  */
 
void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan)
 
{
 
  uint32_t tmp1 = 0U, tmp2 = 0U, tmp3 = 0U;
 
  uint32_t errorcode = HAL_CAN_ERROR_NONE;
 

	
 
  /* Check Overrun flag for FIFO0 */
 
  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FOV0);
 
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FOV0);
 
  if((tmp1 != 0U) && tmp2)
 
  {
 
    /* Set CAN error code to FOV0 error */
 
    errorcode |= HAL_CAN_ERROR_FOV0;
 

	
 
    /* Clear FIFO0 Overrun Flag */
 
    __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV0);
 
  }
 

	
 
  /* Check Overrun flag for FIFO1 */
 
  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FOV1);
 
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FOV1);
 
  if((tmp1 != 0U) && tmp2)
 
  {
 
    /* Set CAN error code to FOV1 error */
 
    errorcode |= HAL_CAN_ERROR_FOV1;
 

	
 
    /* Clear FIFO1 Overrun Flag */
 
    __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV1);
 
  }
 

	
 
  /* Check End of transmission flag */
 
  if(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME))
 
  {
 
    /* Check Transmit request completion status */
 
    tmp1 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_0);
 
    tmp2 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_1);
 
    tmp3 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_2);
 
    if(tmp1 || tmp2 || tmp3)  
 
    {
 
      tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK0);
 
      tmp2 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK1);
 
      tmp3 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK2);
 
      /* Check Transmit success */
 
      if((tmp1) || (tmp2) || (tmp3))
 
      {
 
        /* Call transmit function */
 
        CAN_Transmit_IT(hcan);
 
      }
 
      else /* Transmit failure */
 
      {
 
        /* Set CAN error code to TXFAIL error */
 
        errorcode |= HAL_CAN_ERROR_TXFAIL;
 
      }
 

	
 
      /* Clear transmission status flags (RQCPx and TXOKx) */
 
      SET_BIT(hcan->Instance->TSR, CAN_TSR_RQCP0  | CAN_TSR_RQCP1  | CAN_TSR_RQCP2 | \
 
                                   CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);
 
    }
 
  }
 
  
 
  tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO0);
 
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP0);
 
  /* Check End of reception flag for FIFO0 */
 
  if((tmp1 != 0U) && tmp2)
 
  {
 
    /* Call receive function */
 
    CAN_Receive_IT(hcan, CAN_FIFO0);
 
  }
 
  
 
  tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO1);
 
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP1);
 
  /* Check End of reception flag for FIFO1 */
 
  if((tmp1 != 0U) && tmp2)
 
  {
 
    /* Call receive function */
 
    CAN_Receive_IT(hcan, CAN_FIFO1);
 
  }
 

	
 
  /* Set error code in handle */
 
  hcan->ErrorCode |= errorcode;
 

	
 
  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EWG);
 
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EWG);
 
  tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
 
  /* Check Error Warning Flag */
 
  if(tmp1 && tmp2 && tmp3)
 
  {
 
    /* Set CAN error code to EWG error */
 
    hcan->ErrorCode |= HAL_CAN_ERROR_EWG;
 
    /* No need for clear of Error Warning Flag as read-only */
 
  }
 
  
 
  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EPV);
 
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EPV);
 
  tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR); 
 
  /* Check Error Passive Flag */
 
  if(tmp1 && tmp2 && tmp3)
 
  {
 
    /* Set CAN error code to EPV error */
 
    hcan->ErrorCode |= HAL_CAN_ERROR_EPV;
 
    /* No need for clear of Error Passive Flag as read-only */ 
 
  }
 
  
 
  tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_BOF);
 
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_BOF);
 
  tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);  
 
  /* Check Bus-Off Flag */
 
  if(tmp1 && tmp2 && tmp3)
 
  {
 
    /* Set CAN error code to BOF error */
 
    hcan->ErrorCode |= HAL_CAN_ERROR_BOF;
 
    /* No need for clear of Bus-Off Flag as read-only */
 
  }
 
  
 
  tmp1 = HAL_IS_BIT_CLR(hcan->Instance->ESR, CAN_ESR_LEC);
 
  tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_LEC);
 
  tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
 
  /* Check Last error code Flag */
 
  if((!tmp1) && tmp2 && tmp3)
 
  {
 
    tmp1 = (hcan->Instance->ESR & CAN_ESR_LEC);
 
    switch(tmp1)
 
    {
 
      case(CAN_ESR_LEC_0):
 
          /* Set CAN error code to STF error */
 
          hcan->ErrorCode |= HAL_CAN_ERROR_STF;
 
          break;
 
      case(CAN_ESR_LEC_1):
 
          /* Set CAN error code to FOR error */
 
          hcan->ErrorCode |= HAL_CAN_ERROR_FOR;
 
          break;
 
      case(CAN_ESR_LEC_1 | CAN_ESR_LEC_0):
 
          /* Set CAN error code to ACK error */
 
          hcan->ErrorCode |= HAL_CAN_ERROR_ACK;
 
          break;
 
      case(CAN_ESR_LEC_2):
 
          /* Set CAN error code to BR error */
 
          hcan->ErrorCode |= HAL_CAN_ERROR_BR;
 
          break;
 
      case(CAN_ESR_LEC_2 | CAN_ESR_LEC_0):
 
          /* Set CAN error code to BD error */
 
          hcan->ErrorCode |= HAL_CAN_ERROR_BD;
 
          break;
 
      case(CAN_ESR_LEC_2 | CAN_ESR_LEC_1):
 
          /* Set CAN error code to CRC error */
 
          hcan->ErrorCode |= HAL_CAN_ERROR_CRC;
 
          break;
 
      default:
 
          break;
 
    }
 

	
 
    /* Clear Last error code Flag */ 
 
    CLEAR_BIT(hcan->Instance->ESR, CAN_ESR_LEC);
 
  }
 

	
 
  /* Call the Error call Back in case of Errors */
 
  if(hcan->ErrorCode != HAL_CAN_ERROR_NONE)
 
  {
 
    /* Clear ERRI Flag */ 
 
    hcan->Instance->MSR = CAN_MSR_ERRI; 
 
    /* Set the CAN state ready to be able to start again the process */
 
    hcan->State = HAL_CAN_STATE_READY;
 

	
 
    /* Disable interrupts: */
 
    /*  - Disable Error warning Interrupt */
 
    /*  - Disable Error passive Interrupt */
 
    /*  - Disable Bus-off Interrupt */
 
    /*  - Disable Last error code Interrupt */
 
    /*  - Disable Error Interrupt */
 
    /*  - Disable FIFO 0 message pending Interrupt */
 
    /*  - Disable FIFO 0 Overrun Interrupt */
 
    /*  - Disable FIFO 1 message pending Interrupt */
 
    /*  - Disable FIFO 1 Overrun Interrupt */
 
    /*  - Disable Transmit mailbox empty Interrupt */
 
    __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
 
                               CAN_IT_EPV |
 
                               CAN_IT_BOF |
 
                               CAN_IT_LEC |
 
                               CAN_IT_ERR |
 
                               CAN_IT_FMP0|
 
                               CAN_IT_FOV0|
 
                               CAN_IT_FMP1|
 
                               CAN_IT_FOV1|
 
                               CAN_IT_TME  );
 

	
 
    /* Call Error callback function */
 
    HAL_CAN_ErrorCallback(hcan);
 
  }  
 
}
 

	
 
/**
 
  * @brief  Transmission  complete callback in non blocking mode 
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.
 
  * @retval None
 
  */
 
__weak void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcan);
 
  /* NOTE : This function Should not be modified, when the callback is needed,
 
            the HAL_CAN_TxCpltCallback can be implemented in the user file
 
   */
 
}
 

	
 
/**
 
  * @brief  Transmission  complete callback in non blocking mode 
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.
 
  * @retval None
 
  */
 
__weak void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcan);
 
  /* NOTE : This function Should not be modified, when the callback is needed,
 
            the HAL_CAN_RxCpltCallback can be implemented in the user file
 
   */
 
}
 

	
 
/**
 
  * @brief  Error CAN callback.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.
 
  * @retval None
 
  */
 
__weak void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcan);
 
  /* NOTE : This function Should not be modified, when the callback is needed,
 
            the HAL_CAN_ErrorCallback can be implemented in the user file
 
   */
 
}
 

	
 
/**
 
  * @}
 
  */
 

	
 
/** @defgroup CAN_Exported_Functions_Group3 Peripheral State and Error functions
 
  *  @brief   CAN Peripheral State functions 
 
  *
 
@verbatim   
 
  ==============================================================================
 
            ##### Peripheral State and Error functions #####
 
  ==============================================================================
 
    [..]
 
    This subsection provides functions allowing to :
 
      (+) Check the CAN state.
 
      (+) Check CAN Errors detected during interrupt process
 
         
 
@endverbatim
 
  * @{
 
  */
 

	
 
/**
 
  * @brief  return the CAN state
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.
 
  * @retval HAL state
 
  */
 
HAL_CAN_StateTypeDef HAL_CAN_GetState(CAN_HandleTypeDef* hcan)
 
{
 
  /* Return CAN state */
 
  return hcan->State;
 
}
 

	
 
/**
 
  * @brief  Return the CAN error code
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.
 
  * @retval CAN Error Code
 
  */
 
uint32_t HAL_CAN_GetError(CAN_HandleTypeDef *hcan)
 
{
 
  return hcan->ErrorCode;
 
}
 

	
 
/**
 
  * @}
 
  */
 

	
 
/**
 
  * @}
 
  */
 

	
 
/** @addtogroup CAN_Private_Functions
 
  * @{
 
  */
 
/**
 
  * @brief  Initiates and transmits a CAN frame message.
 
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @retval HAL status
 
  */
 
static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan)
 
{
 
  /* Disable Transmit mailbox empty Interrupt */
 
  __HAL_CAN_DISABLE_IT(hcan, CAN_IT_TME);
 
  
 
  if(hcan->State == HAL_CAN_STATE_BUSY_TX)
 
  {   
 
    /* Disable interrupts: */
 
    /*  - Disable Error warning Interrupt */
 
    /*  - Disable Error passive Interrupt */
 
    /*  - Disable Bus-off Interrupt */
 
    /*  - Disable Last error code Interrupt */
 
    /*  - Disable Error Interrupt */
 
    __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
 
                               CAN_IT_EPV |
 
                               CAN_IT_BOF |
 
                               CAN_IT_LEC |
 
                               CAN_IT_ERR);
 
  }
 

	
 
  /* Change CAN state */
 
  switch(hcan->State)
 
  {
 
    case(HAL_CAN_STATE_BUSY_TX_RX0):
 
      hcan->State = HAL_CAN_STATE_BUSY_RX0;
 
      break;
 
    case(HAL_CAN_STATE_BUSY_TX_RX1):
 
      hcan->State = HAL_CAN_STATE_BUSY_RX1;
 
      break;
 
    case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
 
      hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
 
      break;
 
    default: /* HAL_CAN_STATE_BUSY_TX */
 
      hcan->State = HAL_CAN_STATE_READY;
 
      break;
 
  }
 

	
 
  /* Transmission complete callback */ 
 
  HAL_CAN_TxCpltCallback(hcan);
 
  
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief  Receives a correct CAN frame.
 
  * @param  hcan:       Pointer to a CAN_HandleTypeDef structure that contains
 
  *         the configuration information for the specified CAN.  
 
  * @param  FIFONumber: Specify the FIFO number    
 
  * @retval HAL status
 
  * @retval None
 
  */
 
static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
 
{
 
  uint32_t tmp1 = 0U;
 
  CanRxMsgTypeDef* pRxMsg = NULL;
 

	
 
  /* Set RxMsg pointer */
 
  if(FIFONumber == CAN_FIFO0)
 
  {
 
    pRxMsg = hcan->pRxMsg;
 
  }
 
  else /* FIFONumber == CAN_FIFO1 */
 
  {
 
    pRxMsg = hcan->pRx1Msg;
 
  }
 

	
 
  /* Get the Id */
 
  pRxMsg->IDE = (uint8_t)0x04U & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
 
  if (pRxMsg->IDE == CAN_ID_STD)
 
  {
 
    pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21U);
 
  }
 
  else
 
  {
 
    pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3U);
 
  }
 
  
 
  pRxMsg->RTR = (uint8_t)0x02U & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
 
  /* Get the DLC */
 
  pRxMsg->DLC = (uint8_t)0x0FU & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
 
  /* Get the FIFONumber */
 
  pRxMsg->FIFONumber = FIFONumber;
 
  /* Get the FMI */
 
  pRxMsg->FMI = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8U);
 
  /* Get the data field */
 
  pRxMsg->Data[0] = (uint8_t)0xFFU & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
 
  pRxMsg->Data[1] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8U);
 
  pRxMsg->Data[2] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16U);
 
  pRxMsg->Data[3] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24U);
 
  pRxMsg->Data[4] = (uint8_t)0xFFU & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
 
  pRxMsg->Data[5] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8U);
 
  pRxMsg->Data[6] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16U);
 
  pRxMsg->Data[7] = (uint8_t)0xFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24U);
 
  /* Release the FIFO */
 
  /* Release FIFO0 */
 
  if (FIFONumber == CAN_FIFO0)
 
  {
 
    __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
 
    
 
    /* Disable FIFO 0 overrun and message pending Interrupt */
 
    __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FOV0 | CAN_IT_FMP0);
 
  }
 
  /* Release FIFO1 */
 
  else /* FIFONumber == CAN_FIFO1 */
 
  {
 
    __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
 
    
 
    /* Disable FIFO 1 overrun and message pending Interrupt */
 
    __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FOV1 | CAN_IT_FMP1);
 
  }
 

	
 
  tmp1 = hcan->State;
 
  if((tmp1 == HAL_CAN_STATE_BUSY_RX0) || (tmp1 == HAL_CAN_STATE_BUSY_RX1))
 
  {
 
    /* Disable interrupts: */
 
    /*  - Disable Error warning Interrupt */
 
    /*  - Disable Error passive Interrupt */
 
    /*  - Disable Bus-off Interrupt */
 
    /*  - Disable Last error code Interrupt */
 
    /*  - Disable Error Interrupt */
 
    __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
 
                               CAN_IT_EPV |
 
                               CAN_IT_BOF |
 
                               CAN_IT_LEC |
 
                               CAN_IT_ERR);
 
  }
 

	
 
  /* Change CAN state */
 
  if (FIFONumber == CAN_FIFO0)
 
  {
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_TX_RX0):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_RX0_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_RX1;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
 
        break;
 
      default: /* HAL_CAN_STATE_BUSY_RX0 */
 
        hcan->State = HAL_CAN_STATE_READY;
 
        break;
 
    }
 
  }
 
  else /* FIFONumber == CAN_FIFO1 */
 
  {
 
    switch(hcan->State)
 
    {
 
      case(HAL_CAN_STATE_BUSY_TX_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_RX0_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_RX0;
 
        break;
 
      case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
 
        hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
 
        break;
 
      default: /* HAL_CAN_STATE_BUSY_RX1 */
 
        hcan->State = HAL_CAN_STATE_READY;
 
        break;
 
    }
 
  }
 

	
 
  /* Receive complete callback */ 
 
  HAL_CAN_RxCpltCallback(hcan);
 

	
 
  /* Return function status */
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @}
 
  */
 
#endif /* STM32F103x6) || STM32F103xB || STM32F103xE || STM32F103xG) || STM32F105xC || STM32F107xC */
 

	
 
#endif /* HAL_CAN_MODULE_ENABLED */
 
/**
 
  * @}
 
  */
 

	
 
/**
 
  * @}
 
  */
 

	
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Software/hoverboard-firmware-hack_modified20190825/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cec.c
Show inline comments
 
new file 100644
 
/**
 
  ******************************************************************************
 
  * @file    stm32f1xx_hal_cec.c
 
  * @author  MCD Application Team
 
  * @version V1.1.1
 
  * @date    12-May-2017
 
  * @brief   CEC HAL module driver.
 
  *          This file provides firmware functions to manage the following 
 
  *          functionalities of the High Definition Multimedia Interface 
 
  *          Consumer Electronics Control Peripheral (CEC).
 
  *           + Initialization and de-initialization function
 
  *           + IO operation function
 
  *           + Peripheral Control function
 
  *
 
  *           
 
  @verbatim       
 
 ===============================================================================
 
                        ##### How to use this driver #####
 
 ===============================================================================
 
    [..]
 
    The CEC HAL driver can be used as follow:
 
    
 
    (#) Declare a CEC_HandleTypeDef handle structure.
 
    (#) Initialize the CEC low level resources by implementing the HAL_CEC_MspInit ()API:
 
        (##) Enable the CEC interface clock.
 
        (##) CEC pins configuration:
 
            (+++) Enable the clock for the CEC GPIOs.
 
            (+++) Configure these CEC pins as alternate function pull-up.
 
        (##) NVIC configuration if you need to use interrupt process (HAL_CEC_Transmit_IT()
 
             and HAL_CEC_Receive_IT() APIs):
 
            (+++) Configure the CEC interrupt priority.
 
            (+++) Enable the NVIC CEC IRQ handle.
 
            (+++) The specific CEC interrupts (Transmission complete interrupt, 
 
                  RXNE interrupt and Error Interrupts) will be managed using the macros
 
                  __HAL_CEC_ENABLE_IT() and __HAL_CEC_DISABLE_IT() inside the transmit 
 
                  and receive process.
 

	
 
    (#) Program the Bit Timing Error Mode and the Bit Period Error Mode in the hcec Init structure.
 

	
 
    (#) Initialize the CEC registers by calling the HAL_CEC_Init() API.
 

	
 
  [..]        
 
    (@) This API (HAL_CEC_Init()) configures also the low level Hardware (GPIO, CLOCK, CORTEX...etc)
 
        by calling the customed HAL_CEC_MspInit() API.
 

	
 
  @endverbatim
 
  ******************************************************************************
 
  * @attention
 
  *
 
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
 
  *
 
  * Redistribution and use in source and binary forms, with or without modification,
 
  * are permitted provided that the following conditions are met:
 
  *   1. Redistributions of source code must retain the above copyright notice,
 
  *      this list of conditions and the following disclaimer.
 
  *   2. Redistributions in binary form must reproduce the above copyright notice,
 
  *      this list of conditions and the following disclaimer in the documentation
 
  *      and/or other materials provided with the distribution.
 
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
 
  *      may be used to endorse or promote products derived from this software
 
  *      without specific prior written permission.
 
  *
 
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  *
 
  ******************************************************************************  
 
  */
 

	
 
/* Includes ------------------------------------------------------------------*/
 
#include "stm32f1xx_hal.h"
 

	
 
#ifdef HAL_CEC_MODULE_ENABLED
 

	
 
#if defined(STM32F100xB) || defined(STM32F100xE)
 

	
 
/** @addtogroup STM32F1xx_HAL_Driver
 
  * @{
 
  */
 

	
 
/** @defgroup CEC CEC
 
  * @brief HAL CEC module driver
 
  * @{
 
  */
 

	
 
/* Private typedef -----------------------------------------------------------*/
 
/* Private define ------------------------------------------------------------*/
 
/** @defgroup CEC_Private_Constants CEC Private Constants
 
  * @{
 
  */
 
#define CEC_CFGR_FIELDS (CEC_CFGR_BTEM | CEC_CFGR_BPEM )
 
#define CEC_FLAG_TRANSMIT_MASK (CEC_FLAG_TSOM|CEC_FLAG_TEOM|CEC_FLAG_TBTRF)
 
#define CEC_FLAG_RECEIVE_MASK (CEC_FLAG_RSOM|CEC_FLAG_REOM|CEC_FLAG_RBTF)
 
#define CEC_ESR_ALL_ERROR (CEC_ESR_BTE|CEC_ESR_BPE|CEC_ESR_RBTFE|CEC_ESR_SBE|CEC_ESR_ACKE|CEC_ESR_LINE|CEC_ESR_TBTFE)
 
#define CEC_RXXFERSIZE_INITIALIZE 0xFFFF /*!< Value used to initialise the RxXferSize of the handle */
 
/**
 
  * @}
 
  */
 
 
 
/* Private macro -------------------------------------------------------------*/
 
/* Private variables ---------------------------------------------------------*/
 
/* Private function prototypes -----------------------------------------------*/
 
/** @defgroup CEC_Private_Functions CEC Private Functions
 
  * @{
 
  */
 
static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec);
 
static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec);
 
/**
 
  * @}
 
  */
 
  
 
/* Exported functions ---------------------------------------------------------*/
 

	
 
/** @defgroup CEC_Exported_Functions CEC Exported Functions
 
  * @{
 
  */
 

	
 
/** @defgroup CEC_Exported_Functions_Group1 Initialization and de-initialization functions
 
  *  @brief    Initialization and Configuration functions 
 
  *
 
@verbatim                                                
 
===============================================================================
 
            ##### Initialization and Configuration functions #####
 
 ===============================================================================  
 
    [..]
 
    This subsection provides a set of functions allowing to initialize the CEC
 
      (+) The following parameters need to be configured: 
 
        (++) TimingErrorFree
 
        (++) PeriodErrorFree 
 
        (++) InitiatorAddress
 

	
 
@endverbatim
 
  * @{
 
  */
 

	
 
/**
 
  * @brief Initializes the CEC mode according to the specified
 
  *         parameters in the CEC_InitTypeDef and creates the associated handle .
 
  * @param hcec: CEC handle
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CEC_Init(CEC_HandleTypeDef *hcec)
 
{
 
  /* Check the CEC handle allocation */
 
  if((hcec == NULL) ||(hcec->Init.RxBuffer == NULL))
 
  {
 
    return HAL_ERROR;
 
  }
 

	
 
  /* Check the parameters */ 
 
  assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
 
  assert_param(IS_CEC_BIT_TIMING_ERROR_MODE(hcec->Init.TimingErrorFree));
 
  assert_param(IS_CEC_BIT_PERIOD_ERROR_MODE(hcec->Init.PeriodErrorFree));
 
  assert_param(IS_CEC_ADDRESS(hcec->Init.OwnAddress));
 

	
 
  if(hcec->gState == HAL_CEC_STATE_RESET)
 
  {
 
    /* Allocate lock resource and initialize it */
 
    hcec->Lock = HAL_UNLOCKED;
 
    /* Init the low level hardware : GPIO, CLOCK */
 
    HAL_CEC_MspInit(hcec);
 
  }
 
  hcec->gState = HAL_CEC_STATE_BUSY;
 
  
 
  /* Disable the Peripheral */
 
  __HAL_CEC_DISABLE(hcec);
 
  
 
  /* Write to CEC Control Register */
 
  MODIFY_REG(hcec->Instance->CFGR, CEC_CFGR_FIELDS, hcec->Init.TimingErrorFree | hcec->Init.PeriodErrorFree);
 
  
 
  /* Write to CEC Own Address Register */
 
  MODIFY_REG(hcec->Instance->OAR, CEC_OAR_OA, hcec->Init.OwnAddress);
 
  
 
  /* Configure the prescaler to generate the required 50 microseconds time base.*/
 
  MODIFY_REG(hcec->Instance->PRES, CEC_PRES_PRES, 50U * (HAL_RCC_GetPCLK1Freq()/1000000U) - 1U);
 
  
 
  /* Enable the following CEC Interrupt */
 
  __HAL_CEC_ENABLE_IT(hcec, CEC_IT_IE);
 

	
 
  /* Enable the CEC Peripheral */
 
  __HAL_CEC_ENABLE(hcec);
 
  
 
  hcec->ErrorCode = HAL_CEC_ERROR_NONE;
 
  hcec->gState = HAL_CEC_STATE_READY;
 
  hcec->RxState = HAL_CEC_STATE_READY;
 
  
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief DeInitializes the CEC peripheral 
 
  * @param hcec: CEC handle
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CEC_DeInit(CEC_HandleTypeDef *hcec)
 
{
 
  /* Check the CEC handle allocation */
 
  if(hcec == NULL)
 
  {
 
    return HAL_ERROR;
 
  }
 

	
 
  /* Check the parameters */
 
  assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
 

	
 
  hcec->gState = HAL_CEC_STATE_BUSY;
 

	
 
  /* DeInit the low level hardware */
 
  HAL_CEC_MspDeInit(hcec);
 
  
 
  __HAL_RCC_CEC_FORCE_RESET();
 
  __HAL_RCC_CEC_RELEASE_RESET();
 
  
 
  hcec->ErrorCode = HAL_CEC_ERROR_NONE;
 
  hcec->gState = HAL_CEC_STATE_RESET;
 
  hcec->RxState = HAL_CEC_STATE_RESET;
 
  
 
  /* Process Unlock */
 
  __HAL_UNLOCK(hcec);
 
  
 
  return HAL_OK;
 
}
 

	
 
/**
 
  * @brief Initializes the Own Address of the CEC device
 
  * @param hcec: CEC handle
 
  * @param  CEC_OwnAddress: The CEC own address.  
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CEC_SetDeviceAddress(CEC_HandleTypeDef *hcec, uint16_t CEC_OwnAddress)
 
{
 
  /* Check the parameters */
 
  assert_param(IS_CEC_OWN_ADDRESS(CEC_OwnAddress));
 

	
 
  if ((hcec->gState == HAL_CEC_STATE_READY) && (hcec->RxState == HAL_CEC_STATE_READY))
 
  { 
 
    /* Process Locked */
 
    __HAL_LOCK(hcec); 
 
    
 
    hcec->gState = HAL_CEC_STATE_BUSY;
 
  
 
    /* Disable the Peripheral */
 
    __HAL_CEC_DISABLE(hcec);
 
    
 
    if(CEC_OwnAddress != CEC_OWN_ADDRESS_NONE)
 
    {
 
       MODIFY_REG(hcec->Instance->OAR, CEC_OAR_OA, hcec->Init.OwnAddress);
 
    }
 
    else
 
    {
 
       CLEAR_BIT(hcec->Instance->OAR, CEC_OAR_OA);  
 
    }
 
        
 
    hcec->gState = HAL_CEC_STATE_READY;
 
    hcec->ErrorCode = HAL_CEC_ERROR_NONE;
 
    
 
    /* Process Unlocked */
 
    __HAL_UNLOCK(hcec); 
 
    
 
    /* Enable the Peripheral */
 
    __HAL_CEC_ENABLE(hcec);
 
    
 
    return  HAL_OK; 
 
  }
 
  else
 
  {
 
    return HAL_BUSY;
 
  }
 
}
 

	
 
/**
 
  * @brief CEC MSP Init
 
  * @param hcec: CEC handle
 
  * @retval None
 
  */
 
 __weak void HAL_CEC_MspInit(CEC_HandleTypeDef *hcec)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcec);
 
  /* NOTE : This function should not be modified, when the callback is needed,
 
            the HAL_CEC_MspInit can be implemented in the user file
 
   */ 
 
}
 

	
 
/**
 
  * @brief CEC MSP DeInit
 
  * @param hcec: CEC handle
 
  * @retval None
 
  */
 
 __weak void HAL_CEC_MspDeInit(CEC_HandleTypeDef *hcec)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcec);
 
  /* NOTE : This function should not be modified, when the callback is needed,
 
            the HAL_CEC_MspDeInit can be implemented in the user file
 
   */ 
 
}
 

	
 
/**
 
  * @}
 
  */
 

	
 
/** @defgroup CEC_Exported_Functions_Group2 Input and Output operation functions 
 
  *  @brief CEC Transmit/Receive functions 
 
  *
 
@verbatim   
 
 ===============================================================================
 
                      ##### IO operation functions ##### 
 
 ===============================================================================  
 
    [..]
 
    This subsection provides a set of functions allowing to manage the CEC data transfers.
 
    
 
    (#) The CEC handle must contain the initiator (TX side) and the destination (RX side)
 
        logical addresses (4-bit long addresses, 0xF for broadcast messages destination)
 
    
 
    (#) The communication is performed using Interrupts. 
 
           These API's return the HAL status.
 
           The end of the data processing will be indicated through the 
 
           dedicated CEC IRQ when using Interrupt mode.
 
           The HAL_CEC_TxCpltCallback(), HAL_CEC_RxCpltCallback() user callbacks 
 
           will be executed respectively at the end of the transmit or Receive process
 
           The HAL_CEC_ErrorCallback() user callback will be executed when a communication 
 
           error is detected
 
        
 
    (#) API's with Interrupt are :
 
         (+) HAL_CEC_Transmit_IT()
 
         (+) HAL_CEC_IRQHandler()
 

	
 
    (#) A set of User Callbacks are provided:
 
         (+) HAL_CEC_TxCpltCallback()
 
         (+) HAL_CEC_RxCpltCallback()
 
         (+) HAL_CEC_ErrorCallback()
 
      
 
@endverbatim
 
  * @{
 
  */
 

	
 
/**
 
  * @brief Send data in interrupt mode 
 
  * @param hcec: CEC handle
 
  * @param InitiatorAddress: Initiator address
 
  * @param DestinationAddress: destination logical address      
 
  * @param pData: pointer to input byte data buffer
 
  * @param Size: amount of data to be sent in bytes (without counting the header).
 
  *              0 means only the header is sent (ping operation).
 
  *              Maximum TX size is 15 bytes (1 opcode and up to 14 operands).    
 
  * @retval HAL status
 
  */
 
HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress,uint8_t DestinationAddress, uint8_t *pData, uint32_t Size)
 
{
 
  /* if the IP isn't already busy and if there is no previous transmission
 
     already pending due to arbitration lost */
 
  if(hcec->gState == HAL_CEC_STATE_READY) 
 
  {    
 
    if((pData == NULL ) && (Size > 0U)) 
 
    {
 
      return  HAL_ERROR;
 
    }
 

	
 
    assert_param(IS_CEC_ADDRESS(DestinationAddress));
 
    assert_param(IS_CEC_ADDRESS(InitiatorAddress)); 
 
    assert_param(IS_CEC_MSGSIZE(Size));
 
    
 
    /* Process Locked */
 
    __HAL_LOCK(hcec);
 
    hcec->pTxBuffPtr = pData;
 
    hcec->gState = HAL_CEC_STATE_BUSY_TX;
 
    hcec->ErrorCode = HAL_CEC_ERROR_NONE;
 

	
 
    /* initialize the number of bytes to send,
 
     * 0 means only one header is sent (ping operation) */
 
    hcec->TxXferCount = Size;
 

	
 
    /* send header block */
 
    hcec->Instance->TXD = (uint8_t)((uint32_t)InitiatorAddress << CEC_INITIATOR_LSB_POS) | DestinationAddress;
 
    
 
    /* Process Unlocked */
 
    __HAL_UNLOCK(hcec); 
 

	
 
    /* case no data to be sent, sender is only pinging the system */
 
    if (Size != 0)
 
    {    
 
      /* Set TX Start of Message (TXSOM) bit */
 
      MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TSOM);
 
    }
 
    else
 
    {
 
      /* Send a ping command */
 
      MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM|CEC_FLAG_TSOM);
 
    }
 
    return HAL_OK;
 

	
 
  }
 
  else
 
  {
 
    return HAL_BUSY;   
 
  }
 
}
 

	
 
/**
 
  * @brief Get size of the received frame.
 
  * @param hcec: CEC handle
 
  * @retval Frame size
 
  */
 
uint32_t HAL_CEC_GetLastReceivedFrameSize(CEC_HandleTypeDef *hcec)
 
{
 
  return hcec->RxXferSize;
 
}
 

	
 
/**
 
  * @brief Change Rx Buffer.
 
  * @param hcec: CEC handle
 
  * @param Rxbuffer: Rx Buffer
 
  * @note  This function can be called only inside the HAL_CEC_RxCpltCallback() 
 
  * @retval Frame size
 
  */
 
void HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef *hcec, uint8_t* Rxbuffer)
 
{
 
  hcec->Init.RxBuffer = Rxbuffer; 
 
}
 
  
 
/**
 
  * @brief This function handles CEC interrupt requests.
 
  * @param hcec: CEC handle
 
  * @retval None
 
  */
 
void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
 
{
 
  /* Save error status register for further error handling purposes */
 
  hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
 

	
 
  /* Transmit error */
 
  if(__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TERR) != RESET)
 
  {
 
    /* Acknowledgement of the error */
 
    __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
 
    
 
    hcec->gState = HAL_CEC_STATE_READY;
 
  }
 
  
 
  /* Receive error */
 
  if(__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RERR) != RESET)
 
  {
 
    /* Acknowledgement of the error */
 
    __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
 
    hcec->Init.RxBuffer-=hcec->RxXferSize;
 
    hcec->RxXferSize = 0U; 
 
    hcec->RxState = HAL_CEC_STATE_READY;
 
  }
 
  
 
  if((hcec->ErrorCode & CEC_ESR_ALL_ERROR) != 0U)
 
  {
 
    /* Error  Call Back */
 
    HAL_CEC_ErrorCallback(hcec);
 
  }
 
  
 
  /* Transmit byte request or block transfer finished */
 
  if(__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TBTRF) != RESET)
 
  {
 
    CEC_Transmit_IT(hcec);
 
  }
 

	
 
  /* Receive byte or block transfer finished */
 
  if(__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RBTF) != RESET)
 
  {
 
    if(hcec->RxXferSize == 0U)
 
    {
 
      /* reception is starting */ 
 
      hcec->RxState = HAL_CEC_STATE_BUSY_RX;
 
    }
 
    CEC_Receive_IT(hcec);
 
  }
 
}
 

	
 

	
 
/**
 
  * @brief Tx Transfer completed callback
 
  * @param hcec: CEC handle
 
  * @retval None
 
  */
 
 __weak void HAL_CEC_TxCpltCallback(CEC_HandleTypeDef *hcec)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcec);
 
  /* NOTE : This function should not be modified, when the callback is needed,
 
            the HAL_CEC_TxCpltCallback can be implemented in the user file
 
   */ 
 
}
 

	
 
/**
 
  * @brief Rx Transfer completed callback
 
  * @param hcec: CEC handle
 
  * @param RxFrameSize: Size of frame
 
  * @retval None
 
  */
 
__weak void HAL_CEC_RxCpltCallback(CEC_HandleTypeDef *hcec, uint32_t RxFrameSize)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcec);
 
  UNUSED(RxFrameSize);
 
  /* NOTE : This function should not be modified, when the callback is needed,
 
            the HAL_CEC_RxCpltCallback can be implemented in the user file
 
   */
 
}
 

	
 
/**
 
  * @brief CEC error callbacks
 
  * @param hcec: CEC handle
 
  * @retval None
 
  */
 
 __weak void HAL_CEC_ErrorCallback(CEC_HandleTypeDef *hcec)
 
{
 
  /* Prevent unused argument(s) compilation warning */
 
  UNUSED(hcec);
 
  /* NOTE : This function should not be modified, when the callback is needed,
 
            the HAL_CEC_ErrorCallback can be implemented in the user file
 
   */ 
 
}
 
/**
 
  * @}
 
  */
 

	
 
/** @defgroup CEC_Exported_Functions_Group3 Peripheral Control functions 
 
  *  @brief   CEC control functions 
 
  *
 
@verbatim   
 
 ===============================================================================
 
                      ##### Peripheral Control function #####
 
 ===============================================================================  
 
    [..]
 
    This subsection provides a set of functions allowing to control the CEC.
 
     (+) HAL_CEC_GetState() API can be helpful to check in run-time the state of the CEC peripheral. 
 
	 (+) HAL_CEC_GetError() API can be helpful to check in run-time the error of the CEC peripheral. 
 
@endverbatim
 
  * @{
 
  */
 
/**
 
  * @brief return the CEC state
 
  * @param hcec: pointer to a CEC_HandleTypeDef structure that contains
 
  *              the configuration information for the specified CEC module.
 
  * @retval HAL state
 
  */
 
HAL_CEC_StateTypeDef HAL_CEC_GetState(CEC_HandleTypeDef *hcec)
 
{
 
  uint32_t temp1= 0x00U, temp2 = 0x00U;
 
  temp1 = hcec->gState;
 
  temp2 = hcec->RxState;
 
  
 
  return (HAL_CEC_StateTypeDef)(temp1 | temp2);
 
}
 

	
 
/**
 
* @brief  Return the CEC error code
 
* @param  hcec : pointer to a CEC_HandleTypeDef structure that contains
 
  *              the configuration information for the specified CEC.
 
* @retval CEC Error Code
 
*/
 
uint32_t HAL_CEC_GetError(CEC_HandleTypeDef *hcec)
 
{
 
  return hcec->ErrorCode;
 
}
 

	
 
/**
 
  * @}
 
  */
 

	
 
/**
 
  * @}
 
  */
 

	
 
/** @addtogroup CEC_Private_Functions
 
  * @{
 
  */
 

	
 
 /**
 
  * @brief Send data in interrupt mode 
 
  * @param hcec: CEC handle. 
 
  *         Function called under interruption only, once
 
  *         interruptions have been enabled by HAL_CEC_Transmit_IT()   
 
  * @retval HAL status
 
  */  
 
static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec)
 
{
 
  /* if the IP is already busy or if there is a previous transmission
 
     already pending due to arbitration loss */
 
  if((hcec->gState == HAL_CEC_STATE_BUSY_TX) || (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) != RESET))
 
  {
 
    /* if all data have been sent */
 
    if(hcec->TxXferCount == 0U)
 
    {
 
      /* Acknowledge successful completion by writing 0x00 */
 
      MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00U);
 

	
 
      hcec->gState = HAL_CEC_STATE_READY;
 
      
 
      HAL_CEC_TxCpltCallback(hcec);
 
      
 
      return HAL_OK;
 
    }
 
    else
 
    {
 
      /* Reduce the number of bytes to transfer by one */
 
      hcec->TxXferCount--;
 
      
 
      /* Write data to TX buffer*/
 
      hcec->Instance->TXD = *hcec->pTxBuffPtr++;
 
      
 
      /* If this is the last byte of the ongoing transmission */
 
      if(hcec->TxXferCount == 0U)
 
      {
 
        /* Acknowledge byte request and signal end of message */
 
        MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM);
 
      }
 
      else
 
      {
 
        /* Acknowledge byte request by writing 0x00 */
 
        MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00U);
 
      }  
 
      
 
      return HAL_OK;
 
    }
 
  }
 
  else
 
  {
 
    return HAL_BUSY;   
 
  }
 
}
 

	
 
/**
 
  * @brief Receive data in interrupt mode. 
 
  * @param hcec: CEC handle.
 
  *         Function called under interruption only, once
 
  *         interruptions have been enabled by HAL_CEC_Receive_IT()   
 
  * @retval HAL status
 
  */  
 
static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec)
 
{
 
  static uint32_t temp;
 
  
 
  if(hcec->RxState == HAL_CEC_STATE_BUSY_RX)
 
  {
 
    temp = hcec->Instance->CSR;
 
    
 
    /* Store received data */
 
    hcec->RxXferSize++;
 
    *hcec->Init.RxBuffer++ = hcec->Instance->RXD;
 
    
 
    /* Acknowledge received byte by writing 0x00 */
 
    MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_RECEIVE_MASK, 0x00U);
 
    
 
    /* If the End Of Message is reached */
 
    if(HAL_IS_BIT_SET(temp, CEC_FLAG_REOM))
 
    {
 
      /* Interrupts are not disabled due to transmission still ongoing */
 
      hcec->RxState = HAL_CEC_STATE_READY;
 
      
 
      HAL_CEC_RxCpltCallback(hcec, hcec->RxXferSize);
 
      
 
      return HAL_OK;
 
    }
 
    else
 
    {
 
      return HAL_BUSY; 
 
    }
 
  }
 
  else
 
  {
 
    return HAL_BUSY; 
 
  }
 
}
 

	
 
/**
 
 * @}
 
 */ 
 
 
 
/**
 
  * @}
 
  */
 

	
 
#endif /* defined(STM32F100xB) || defined(STM32F100xE) */
 

	
 
#endif /* HAL_CEC_MODULE_ENABLED */
 
/**
 
  * @}
 
  */
 

	
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Changeset was too big and was cut off... Show full diff anyway

0 comments (0 inline, 0 general)